Someone said recently that they thought extensions methods required a new CLR.

最近有人说他们认为扩展方法需要新的CLR。

Extension methods are a new feature in .NET 3.5 (C#3/VB9) that let you appear to "spot weld" new methods on to existing classes. If you think that the "string" object needs a new method, you can just add it and call it on instance variables.

扩展方法是.NET 3.5(C#3 / VB9)中的一项新功能,使您似乎可以将新方法“点焊”到现有类上。 如果您认为“字符串”对象需要新方法,则可以添加它并在实例变量上调用它。

Here's an example. Note that the IntHelper35 class below defines a new method for integers called DoubleThenAdd. Now, I can do things like 2.DoubleThenAdd(2). See how the method directly "hangs off" of the integer 2? It's the "this" keyword appearing before the first parameter that makes this magic work. But is it really magic? Did it require a change to the CLR, or just a really smart compiler?

这是一个例子。 请注意,下面的IntHelper35类为整数定义了一个称为DoubleThenAdd的新方法。 现在,我可以执行2.DoubleThenAdd(2)之类的操作。 看看方法如何直接“挂断”整数2? 使这个魔术起作用的第一个参数之前是“ this”关键字。 但这真的是魔术吗? 是否需要更改CLR或仅是真正的智能编译器?

Let's do some experimenting and see if we can figure it out for ourselves.

让我们做一些实验,看看是否可以自己解决。

using System;namespace Foo{    class Program    {        static void Main(string[] args)        {            Console.WriteLine(2.DoubleThenAdd(3));            Console.WriteLine(IntHelper20.DoubleThenAdd(2, 3));            Console.ReadLine();        }    }

    public static class IntHelper20    {        public static int DoubleThenAdd(int myInt, int x)        {            return myInt + (2 * x);        }    }

    public static class IntHelper35    {        public static int DoubleThenAdd(this int myInt, int x)        {            return myInt + (2 * x);        }    }}

I've also added an IntHelper20 class with an identical method but WITHOUT the "this" keyboard. It's a standard static method, and I call it in the standard way. Now, let's compile it, then disassemble it with Reflector and take a look at the IL (Intermediate Language).

我还添加了具有相同方法但没有“ this”键盘的IntHelper20类。 这是一个标准的静态方法,我以标准方式进行调用。 现在,让我们对其进行编译,然后使用Reflector对其进行分解,然后看看IL(中间语言)。

.method private hidebysig static void Main(string[] args) cil managed{    .entrypoint    .maxstack 8    L_0000: nop     L_0001: ldc.i4.2     L_0002: ldc.i4.3     L_0003: call int32 ConsoleApplication8.IntHelper35::DoubleThenAdd(int32, int32)    L_0008: call void [mscorlib]System.Console::WriteLine(int32)    L_000d: nop     L_000e: ldc.i4.2     L_000f: ldc.i4.3     L_0010: call int32 ConsoleApplication8.IntHelper20::DoubleThenAdd(int32, int32)    L_0015: call void [mscorlib]System.Console::WriteLine(int32)    L_001a: nop     L_001b: call string [mscorlib]System.Console::ReadLine()    L_0020: pop     L_0021: ret }

Interestingly, both method calls look the same. They look like static method calls with two integer parameters. From looking at this part of the IL, you can't actually tell which one is an extension method. We know the first one, IntHelper35, is, but from this snippet of IL, we can't tell.

有趣的是,两个方法调用看起来都一样。 它们看起来像带有两个整数参数的静态方法调用。 通过查看IL的这一部分,您实际上无法分辨出哪一种是扩展方法。 我们知道第一个是IntHelper35,但是从IL的这一片段中我们无法确定。

Can Reflector tell the difference if we ask it to decompile to C# or VB (rather than IL)?

如果我们要求将其反编译为C#或VB(而不是IL),则Reflector能否分辨出差异?

private static void Main(string[] args){    Console.WriteLine(2.DoubleThenAdd(3));    Console.WriteLine(IntHelper20.DoubleThenAdd(2, 3));    Console.ReadLine();} 

Interestingly, it knows the difference. How? Here's the decompilation of the IntHelper35 class itself:

有趣的是,它知道区别。 怎么样? 这是IntHelper35类本身的反编译:

.method public hidebysig static int32 DoubleThenAdd(int32 myInt, int32 x) cil managed{    .custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor()    .maxstack 3    .locals init (        [0] int32 CS$1$0000)    L_0000: nop     L_0001: ldarg.0     L_0002: ldc.i4.2     L_0003: ldarg.1     L_0004: mul     L_0005: add     L_0006: stloc.0     L_0007: br.s L_0009    L_0009: ldloc.0     L_000a: ret }

The only difference between the two methods is the CompilerServices.ExtensionAttribute. This attribute is added because of the "this" keyword, and it looks like it's what Reflector is using to correctly identify the extension method.

两种方法之间的唯一区别是CompilerServices.ExtensionAttribute。 添加此属性的原因是使用了“ this”关键字,它看起来像是Reflector用来正确标识扩展方法的对象。

Extension methods are a really nice syntactic sugar. They're not really added to the class, as we can see, but the compiler makes it feel like they are.

扩展方法是一个非常不错的语法糖。 正如我们所看到的,它们并没有真正添加到类中,但是编译器使它们看起来像它们一样。

关于面向对象的“ C”略有相关 (Slightly Related Aside about Object Oriented "C")

This reminded me of what we called "object oriented C" in college. I found a great example on Phil Bolthole's site.

这使我想起了大学时期所谓的“面向对象的C”。 我在Phil Bolthole的网站上找到了一个很好的例子。

Basically you make a struct to represent your member variables, and then you create a number of methods where the first parameter is the struct. For example:

基本上,您会构造一个表示成员变量的结构,然后创建许多方法,其中第一个参数是该结构。 例如:

#include "FooOBJ.h" void diddle(){    FooOBJ fobj;

    fobj=newFooOBJ(); /* create a new object of type "FooOBJ" */

 /* Perform member functions on FooOBJ.     * If you try these functions on a different type of object,   * you will get a compile-time error   */   setFooNumber(fobj, 1);    setFooString(fobj, "somestring");   dumpFooState(fobj);

 deleteFooOBJ(fobj);}

int main(){ diddle(); return 0;}

In this C example, if you mentally move the first parameter to the left side and add a ".", like fobj.dumpFooState() it's almost like C++. Then, you ask yourself, "gosh, wouldn't it be nice if a compiler did this for me?"

在此C示例中,如果您在脑海中将第一个参数移到左侧并添加“。”,例如fobj.dumpFooState(),则几乎就像C ++。 然后,你问自己:“天哪,如果编译器为我这样做好吗?”

C#, C# .NET 3.5, ,.NET 3.5 , OOP OOP

翻译自: https://www.hanselman.com/blog/how-do-extension-methods-work-and-why-was-a-new-clr-not-required

扩展方法如何工作,为什么不需要新的CLR?相关推荐

  1. ES6新特性_ES6的对象扩展方法---JavaScript_ECMAScript_ES6-ES11新特性工作笔记040

    然后我们看一下es6中的对象扩展方法 可以看到有个Object.is(120,121); 这个相当于判断是否相等,也就是是否是某个对象. 可以看到120,和121 不相等. 然后120和120相等. ...

  2. .NET中那些所谓的新语法之二:匿名类、匿名方法与扩展方法

    开篇:在上一篇中,我们了解了自动属性.隐式类型.自动初始化器等所谓的新语法,这一篇我们继续征程,看看匿名类.匿名方法以及常用的扩展方法.虽然,都是很常见的东西,但是未必我们都明白其中蕴含的奥妙.所以, ...

  3. (转)[翻译] ASP.NET MVC Tip #1 - 使用扩展方法创建新的HTML Helper

    原文地址:http://weblogs.asp.net/stephenwalther/archive/2008/06/13/asp-net-mvc-tip-1-creating-new-html-he ...

  4. Enumerable 下又有新的扩展方法啦,快来一睹为快吧

    一:背景 1. 讲故事 前段时间将公司的一个项目从 4.5 升级到了 framework 4.8 ,编码的时候发现 Enumerable 中多了三个扩展方法: Append, Prepend, ToH ...

  5. [易学C#]C#3.0语言新特性之扩展方法

    当我们需要对已有类的功能进行扩展时,我们通常会想到继承,继承已有类,然后为其加入新的行为.而C# 3.0中加入的扩展方法(Extension Methods)特性,则提供了另一种实现功能扩展的方式. ...

  6. C#.Net工作笔记010---c#中的静态扩展方法_可动态给string等_添加共通方法好用

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 之前,给list添加排序的扩展方法的时候用过.下面的作用是去掉list中重复的数据. /// &l ...

  7. C# 3.0新特性之扩展方法

    C#3.0扩展方法是给现有类型添加一个方法.现在类型既可是基本数据类型(如int,String等),也可以是自己定义的类. //Demo--1 //扩展基本类型 namespace TestExten ...

  8. C#3.0新特性 扩展方法

    扩展方法可以使我们为现有的添加方法,现有的类可是是CLB的也可以是自己定义的. 注意事项:   通过this修饰方法第一个参数  方法声明在静态类中  方法通过对象调用 重要注意事项:   扩展方法和 ...

  9. 用 .NET 3.5 创建 ToJSON() 扩展方法

    今年早些时候,我通过blog介绍了 C# 和 VB 语言的一项新的扩充特性"扩展方法". 扩展方法让开发者可以向已有的 CLR 类型的公共契约中添加新的方法,而不需要子类化或重新编 ...

最新文章

  1. Android中的ImageView的getDrawableCache获取背景图片的时候注意的问题
  2. Tomcat Filter 源码分析
  3. Python 列表count()函数元素次数统计
  4. protobuf java基础
  5. spring源码分析,聊聊PropertyPlaceholderConfigurer
  6. 计算机视觉——openCV的简介
  7. 程式CSCMSV4黑色炫酷DJ音乐门户模板 音乐网源码
  8. JDK 5、6、7、8、9、10、11、12、13、14 新特性汇总
  9. 将VS Code用于C#脚本
  10. QRegExpValidator
  11. 20.高性能MySQL --- 在MySQL上使用 Sphinx
  12. Hibernate(转载)
  13. Flutter关于简单的吸顶通讯录制作
  14. ssm企业人事管理系统
  15. [置顶] 以盛唐气象,浇胸中块垒:唐诗与宋词学习笔记汇总目录
  16. go-http server使用hijack接管连接的管理
  17. android 强制卸载app,怎么强制删除安卓手机自带软件(三招就能卸载干净)
  18. inline-block是什么意思
  19. 解决log4j2子线程无法获取到traceId问题
  20. 集成学习-Bagging和Pasting

热门文章

  1. 暴力/蛮力法经典例题--最大连续子序列和--C语言
  2. 【机器翻译】调优和测评
  3. matlab 拟合成指数函数,matlab中用nlinfit拟合指数函数f=a*exp(b*x)+c*exp(d*x)
  4. AndroidStudio 图像随键盘按动在屏幕移动(按键事件)
  5. C、C++和C#的关系,以“把大象放进冰箱里”举例
  6. mysql数据库快速传输方案_MySQL数据库迁移快速导出导入大量数据
  7. 【Android】 Color 颜色设置
  8. Echarts x轴标签太长解决方案
  9. 「架构远景·」TOGAF建模:价值链图
  10. 【CV-project】看图说话(Image Captioning)