为什么不在嵌套类中允许扩展方法定义?

时间:2012-07-12 01:20:20

标签: 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);
      }
   }
}

而现在我必须创建一个单独的独立课程。

更新/注意:我没想到它是内部类的事实会影响扩展方法的可用性范围。我只想解决一个单独的具有单独名称的实际编码问题。

3 个答案:

答案 0 :(得分:4)

这里的关键点是嵌套类可以访问外部类中的私有字段

以下代码有效:

public class Foo
{
    private bool _field;

    public static class Extensions
    {
        public static bool GetField(Foo foo)
        {
            return foo._field;
        }
    }
}

在这里你明确地传入了一个类的实例,并允许一个静态方法访问一个私有字段......似乎是合理的:

bool fieldValue = Foo.Extensions.GetField(new Foo());

但是,虽然扩展方法只是静态方法的替代语法,但它们的调用方式与非静态实例方法相同。

现在,如果在嵌套类中允许扩展方法,它们实际上可以访问私有字段,并且它们将更接近实例方法。 这可能导致一些意想不到的后果。

总之,如果允许这样做:

public class Foo
{
    private bool _field;

    public static class Extensions
    {
        public static bool GetField(*this* Foo foo) // not allowed, compile error.
        {
            return foo._field;
        }
    }
}

然后您可以编写以下代码,使扩展方法的行为更像实例方法:

var foo = new Foo();
var iGotAPrivateField = foo.GetField();

根据评论进行修改

为什么扩展方法与实例方法等效是一个坏主意?

Eric Lippert's words(强调我的):

  

所以,是的,经常听到的批评“扩展方法不是面向对象”是完全正确的,但也是无关紧要的。扩展方法当然不是面向对象的。他们把操纵数据的代码远离声明数据的代码,他们不能破坏封装并与对象的私有状态交谈它们似乎是方法,它们不能很好地发挥作用继承,等等。它们是一种方便的面向对象服装的程序式编程。

答案 1 :(得分:2)

没有技术原因 - 只是实用。如果您的扩展方法的范围受限于单个类,只需将其定义为类中的常规静态方法并删除“this”即可。扩展程序用于跨多个类共享。

答案 2 :(得分:1)

我想禁止这件事背后的想法是因为扩展方法适用于命名空间中的所有实体。

如果要创建嵌套的Extension Methods类,那么它将仅适用于嵌套的类。在这种情况下,它不是创建扩展方法的点。然后任何正常的非扩展方法都可以。