扩展方法在内部是如何实现的

9
扩展方法是如何在内部实现的?也就是说,当编译器看到扩展方法的声明时会发生什么,以及当调用扩展方法时运行时会发生什么。
是否涉及反射?或者当您有一个扩展方法时,它的代码是否注入目标类类型元数据中,并附加一些额外的标志来说明这是一个扩展方法,然后CLR知道如何处理它?
总之,在幕后会发生什么?
7个回答

10

正如其他同事已经说过的,它只是一个静态方法。 从编译器的角度来看,我们可以说CLR甚至对扩展方法一无所知。 你可以尝试检查IL代码。。

这里有一个例子

static class ExtendedString
{
    public static String TestMethod(this String str, String someParam)
    {
        return someParam;
    }
}

static void Main(string[] args)
{
    String str = String.Empty;
    Console.WriteLine(str.TestMethod("Hello World!!"));
    ........
}

这里是IL代码。

  IL_0001:  ldsfld     string [mscorlib]System.String::Empty
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldstr      "Hello World!!"
  IL_000d:  call       string StringPooling.ExtendedString::TestMethod(string,
                                                                       string)
  IL_0012:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0017:  nop

正如您所看到的,这只是一个静态方法的调用。 该方法没有添加到类中,但编译器使其看起来像是添加了。 而在反射层面,您唯一能看到的区别是添加了CompilerServices.ExtensionAttribute。


4
扩展方法被转换为静态函数。换句话说,它们是静态函数的语法糖。

2

我认为反射与扩展方法无关。扩展方法的处理方式与在助手类中编写静态助手函数相同,唯一的区别是编译器替你完成这项工作。


1

为了澄清上面的答案... 扩展方法是静态函数。.NET 3.5中的附加功能使它们被解释为类型中的新方法。


0

是的,扩展方法只是静态方法。它们与它们所谓“扩展”的类没有额外的特权。然而,编译器确实使用ExtensionAttribute标记“扩展”静态方法。您可以在IL中看到这一点。这使得编译器将其特殊处理,因此您实际上无法将其作为常规静态方法调用。例如,以下代码将无法编译:

var test = new [] { "Goodbye", "Cruel", "World" };
var result = IEnumerable<string>.Where<string>(test, s => s.Length > 5);

尽管这是在幕后发生的事情。

但正如LukeH在下面指出的那样,您可以在实际定义它的类上调用它...我太傻了。


你可以直接调用扩展方法作为静态方法,它只是在不同的静态类上的静态方法:var result = Enumerable.Where<string>(test, s => s.Length > 5); - LukeH
你说得完全正确。试图在“扩展”的类型上调用它是没有意义的。我的失误。 - Einar

0

0

扩展方法与static方法非常相似,唯一的区别在于它具有一个属性CompilerServices.ExtensionAttribute,这有助于将其识别为扩展方法。

您可以阅读此内容


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接