C# 如何在内部实现扩展方法
扩展方法是如何在内部实现的?我指的是当编译器看到扩展方法的声明时会发生什么,以及当调用扩展方法时在运行时会发生什么 是否涉及反思?或者,当您有一个扩展方法时,它的代码是否被注入到目标类类型元数据中,并带有一些附加标志,指出这是一个扩展方法,然后CLR知道如何处理它C# 如何在内部实现扩展方法,c#,.net,clr,C#,.net,Clr,扩展方法是如何在内部实现的?我指的是当编译器看到扩展方法的声明时会发生什么,以及当调用扩展方法时在运行时会发生什么 是否涉及反思?或者,当您有一个扩展方法时,它的代码是否被注入到目标类类型元数据中,并带有一些附加标志,指出这是一个扩展方法,然后CLR知道如何处理它 一般来说,在引擎盖下会发生什么?扩展方法被转换为静态函数。换句话说,它们是静态函数的语法糖。我认为扩展方法中不涉及反射。扩展方法的处理方式与您在助手类中编写静态助手函数的处理方式相同,唯一的区别是编译器为您执行此操作。为了澄清上述答案
一般来说,在引擎盖下会发生什么?扩展方法被转换为静态函数。换句话说,它们是静态函数的语法糖。我认为扩展方法中不涉及反射。扩展方法的处理方式与您在
助手类
中编写静态助手函数
的处理方式相同,唯一的区别是编译器为您执行此操作。为了澄清上述答案。。。扩展方法是静态函数。NET 3.5中的附加功能允许将它们解释为所讨论类型上的新方法 扩展方法只是静态方法。唯一的区别是VisualStudio编辑器等工具带来的,它为自动完成(intellisense)功能弹出它们。您可以在这里找到详细的解释:扩展方法与静态方法非常相似,唯一的区别在于它有一个属性CompilerServices.ExtensionAttribute
,这有助于将其识别为扩展方法
您可以是的,扩展方法只是静态方法。对于他们所谓“扩展”的类,他们没有额外的特权。但是,编译器确实使用ExtensionAttribute标记“extension”静态方法。你可以在IL中看到这一点。这使得编译器对它进行特殊处理,因此您实际上无法将其作为常规静态方法调用。例如,这不会编译:
var test = new [] { "Goodbye", "Cruel", "World" };
var result = IEnumerable<string>.Where<string>(test, s => s.Length > 5);
var test=new[]{“再见”、“残酷”、“世界”};
var result=IEnumerable.Where(测试,s=>s.Length>5);
即使这是引擎盖下发生的事情
但正如LukeH在下面指出的,您可以在实际定义它的类上调用它。。。我真傻。正如其他同事所说,这只是一种静态方法。
这都是关于编译器的,我们可以说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。您可以直接作为静态方法调用扩展方法,它只是另一个静态类上的静态方法:var result=Enumerable.Where(test,s=>s.Length>5)你完全正确。尝试在“扩展”的类型之外调用它是没有意义的。我的错。