我们目前正在讨论 .NET 中的扩展方法是否不好。或者在什么情况下扩展方法会引入难以发现的错误或以任何其他方式出现意外行为。
我们想出了:
- 为不受您控制的类型编写扩展方法(例如,使用 GetTotalSize() 扩展 DirectoryInfo 等)是不好的,因为 API 的所有者可能会引入隐藏我们扩展的方法 - 并且可能有不同的边缘情况。例如,如果由于隐藏而不再使用扩展方法,则在扩展方法中测试 null 将自动转换为 NullReferenceException。
问题:
- 除了“躲藏”之外,还有其他我们没有想到的危险情况吗?
编辑:
另一种非常危险的情况。 假设你有一个扩展方法:
namespace Example.ExtensionMethods
{
public static class Extension
{
public static int Conflict(this TestMe obj)
{
return -1;
}
}
}
并使用它:
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));
}
}
}
请注意,您使用它的命名空间更长。
现在你用这个引用一个dll:
namespace Example.ExtensionMethods.Conflict
{
public static class ConflictExtension
{
public static int Conflict(this TestMe obj)
{
return 1;
}
}
}
你的测试会失败!它将编译而不会出现编译器错误。它会简单地失败。您甚至不必指定“使用 Example.ExtensionMethods.Conflict”。编译器将遍历命名空间名称并在 Example.ExtensionMethods.Extension 之前找到 Example.ExtensionMethods.Conflict.ConflictExtension 并将使用它而不会提示不明确的扩展方法。哦,太恐怖了!
最佳答案
一些好奇心:
- 可能会在
null
上调用扩展方法实例;这可能会令人困惑(但有时很有用) - 如果他们有不同的意图,“隐藏”问题是个大问题
- 同样,您可能会从 2 个不同的命名空间获得具有相同名称的不同扩展方法;如果您只有两个命名空间中的一个,这可能会导致不一致的行为(取决于哪个)...
- ...但是如果有人在您的代码使用的第二个命名空间中添加了一个类似(相同的签名)扩展方法,它将在编译时中断(不明确)
(编辑)当然,还有“Nullable<T>
/new()
”炸弹(see here)...
关于c# - 扩展方法何时中断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/610870/