Aar*_*ide 10 c# extension-methods
我会发现在嵌套类中为类编写我的exensions是方便/合理的.主要原因是我可以简单地命名该类,Extensions并让它的外部命名范围为编译器提供唯一的类型名称.
拒绝以下内容的技术原因是什么:
public class Foo
{
ObjectSet<Bar> Bars { get; set; }
public static class Extensions
{
public static Bar ByName(this ObjectSet<Bar> bars, string name)
{
return bars.FirstOrDefault(c => c.Name == name);
}
}
}
Run Code Online (Sandbox Code Playgroud)
而现在我必须创建一个单独的独立课程.
更新/注意:我没想到它是一个内部类会影响扩展方法的可用范围.我只想解决实际编码问题一个单独的具有单独名称的类.
这里的关键点是嵌套类可以访问外部类中的私有字段.
以下代码有效:
public class Foo
{
private bool _field;
public static class Extensions
{
public static bool GetField(Foo foo)
{
return foo._field;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里你明确地传入了一个类的实例,并允许一个静态方法访问一个私有字段...似乎合理:
bool fieldValue = Foo.Extensions.GetField(new Foo());
Run Code Online (Sandbox Code Playgroud)
但是,虽然扩展方法只是静态方法的替代语法,但它们的调用方式与非静态实例方法相同.
现在,如果在嵌套类中允许扩展方法,它们实际上可以访问私有字段,并且它们将更接近实例方法.这可能会导致一些意想不到的后果.
总之,如果允许这样做:
public class Foo
{
private bool _field;
public static class Extensions
{
public static bool GetField(*this* Foo foo) // not allowed, compile error.
{
return foo._field;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以编写下面的代码,使扩展方法的行为更像一个实例方法,它应该是:
var foo = new Foo();
var iGotAPrivateField = foo.GetField();
Run Code Online (Sandbox Code Playgroud)
根据评论进行编辑
为什么扩展方法等同于实例方法是个坏主意?
所以,是的,经常听到的批评"扩展方法不是面向对象"是完全正确的,但也相当无关紧要.扩展方法当然不是面向对象的.他们将操纵数据的代码放在远离声明数据的代码的位置,它们不能破坏封装并与它们看起来是方法的对象的私有状态交谈,它们不能很好地继承,等等.它们是一种方便的面向对象服装的程序编程.
我猜想不允许这个事情背后的想法是因为扩展方法适用于跨命名空间的所有实体。
如果您将创建一个嵌套的扩展方法类,那么它将仅适用于嵌套它的类。在这种情况下,没有必要创建扩展方法。那么任何正常的非扩展方法都可以。