扩展方法什么时候破坏?

Tob*_*orn 12 .net c# extension-methods

我们目前正在讨论.NET中的扩展方法是否坏.或者在什么情况下,扩展方法可以引入难以发现的错误或以任何其他方式出乎意料地行为.

我们想出了:

  • 为不受您控制的类型编写扩展方法(例如,使用GetTotalSize()扩展DirectoryInfo等)是不好的,因为API的所有者可能会引入隐藏扩展的方法 - 并且可能有不同的边缘情况.例如,如果由于隐藏而不再使用扩展方法,则在扩展方法中对null进行测试将自动转换为NullReferenceException.

题:

  • 除了"隐藏"我们没有想到的任何其他危险情况吗?

编辑:

另一个非常危险的情况 假设您有一个扩展方法:

namespace Example.ExtensionMethods
{
    public static class Extension
    {
        public static int Conflict(this TestMe obj)
        {
            return -1;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并使用它:

namespace Example.ExtensionMethods.Conflict.Test
{
    [TestFixture]
    public class ConflictExtensionTest
    {
        [Test]
        public void ConflictTest()
        {
            TestMe me = new TestMe();
            int result = me.Conflict();
            Assert.That(result, Is.EqualTo(-1));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,您使用它的命名空间更长.

现在你用这个引用一个dll:

namespace Example.ExtensionMethods.Conflict
{
    public static class ConflictExtension
    {
        public static int Conflict(this TestMe obj)
        {
            return 1;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

而你的测试将失败!它将编译而没有编译器错误.它会失败.没有你甚至不必指定"使用Example.ExtensionMethods.Conflict".编译器将遍历命名空间名称并在Example.ExtensionMethods.Extension之前找到Example.ExtensionMethods.Conflict.ConflictExtension,并且将使用它而不会抱怨模糊的扩展方法.哦,恐怖!

Mar*_*ell 9

一些好奇心:

  • 可以在null实例上调用扩展方法; 这可能会令人困惑(但有时很有用)
  • 如果他们有不同的意图,"隐藏"问题是一个大问题
  • 同样,您可能会从2个不同的命名空间中获得具有相同名称的不同扩展方法; 如果你只有一个两个命名空间,这可能导致不一致的行为(取决于)...
  • ...但是如果有人在您的代码使用的第二个命名空间中添加了类似(相同的签名)扩展方法,它将在编译时中断(不明确)

(编辑)当然,还有" Nullable<T>/ new()"炸弹(见这里)......


Chu*_*way 5

我不同意,扩展方法的全部意义在于将您的成员添加到黑盒子类中.像其他一切都有陷阱,你必须注意命名,实现和理解方法的啄食顺序.

  • 可以认为静态辅助类在该特定场景中同样有用 - 并且危险性要小得多. (2认同)