我最近一直在重构一些旧代码,许多方法可用作基础类型的扩展方法,例如double
,float
,int
,string
等等。但是,随着我不断进步,我想到了一个想法。有多种方法可以访问扩展方法。让我们创建一个名为Extensions
的容器类,并添加一个基本的扩展方法(首先),然后使用一个简单的方法调用一个伪类Dummy
,该方法利用我们的扩展方法称为DoIt
。
public static class Extensions {
public static double ToRadians(this double degrees) => degrees * Math.PI / 180.0;
}
public class Dummy {
public void DoIt() {
double radians = Extensions.ToRadians(45.0);
double degrees = 90.0;
radians = degrees.ToRadians();
}
}
这不是最优雅的示例,但是它演示了对扩展方法的广泛了解。现在,为我们的WasteOfTime
类创建一个愚蠢且毫无意义的扩展,名为Dummy
,但要在Extensions
类之内。
我不确定您为什么要这样做,但是出于疑问,让我们开始吧!
public static class Extensions {
...
public static void WasteOfTime(this Dummy dummy) { }
...
}
好的,现在我们有了这个完美的小方法,应该将其放在Dummy
类中。好吧,由于扩展方法仅适用于类型实例,因此您应该能够从WasteOfTime
类的特殊方法Dummy
调用DoIt
。
public void DoIt() {
...
WasteOfTime();
...
}
哦,但是等等,你不能那样做!找不到方法!让我们用this
关键字来限定它!
this.WasteOfTime();
那更好,它可以编译!有用!浪费时间!酷!
我不考虑实际执行此操作,但是出于好奇,我尝试了一下。如果您可以给出一个有效的例子说明为什么这将是一个好主意,请随时分享,但我相信这就是其中之一。 您在想什么 实施方式。
由于现代编译器无需使用this
关键字来限定字段,属性和方法,为什么我必须限定扩展方法?
我唯一能想到的是扩展方法在技术上对基类是静态的。
答案 0 :(得分:3)
首先,我会注意到有充分的理由在this
上调用扩展方法。例如,您可能正在编写一个收集类,并想在其中使用LINQ。没有错。现在,就问题而言:
由于现代编译器无需使用this关键字来限定字段,属性和方法,为什么我必须限定扩展方法?
这与编译器的现代性无关,它与语言规范的内容有关。从ECMA-334,第12.7.6.3节:
在其中一种形式的方法调用(第1.2.6.6.2节)中
expr . identifier ( ) expr . identifier ( args ) expr . identifier < typeargs > ( ) expr . identifier < typeargs > ( args )
如果调用的正常处理未找到适用的方法,则尝试将构造作为扩展方法调用进行处理。如果expr或任何args的编译时类型为
dynamic
,则扩展方法将不适用。
采用Method()
形式的方法调用不是,因为没有expr
。
因此,编译器仅遵循规范的规则。至于为什么这样设计,则略有不同。我不知道它的详细信息(尽管我可以看到它们是否在规范的带注释的版本中),但是我怀疑Foo()
可以引用实例方法或静态方法的事实当前类或任何基类中的方法使整个过程变得有些棘手。 (请注意,从C#6开始,在using static
指令导入的任何方法中,它也可能是静态方法。)