Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中的扩展方法:为什么这样做?_C#_Static_Extension Methods_This_Legacy Code - Fatal编程技术网

C#中的扩展方法:为什么这样做?

C#中的扩展方法:为什么这样做?,c#,static,extension-methods,this,legacy-code,C#,Static,Extension Methods,This,Legacy Code,我有点困惑,为什么这不会给出一个错误。我在一些过时的遗留软件中发现了这段代码,并惊讶地发现它可以工作 public static string CleanFileName(this string fileName) { return CleanFileName(fileName, 64); } public static string CleanFileName(this string fileName, int maxLength) { //some logic } 我对扩展方法的

我有点困惑,为什么这不会给出一个错误。我在一些过时的遗留软件中发现了这段代码,并惊讶地发现它可以工作

public static string CleanFileName(this string fileName)
{
  return CleanFileName(fileName, 64);
}

public static string CleanFileName(this string fileName, int maxLength)
{
  //some logic
}
我对扩展方法的经验是这样称呼它:

fileName.CleanFileName(64);

这仅仅是因为它也是一种静态方法吗?这是一种常见的做法,只是我还没有见过的东西,还是一段过时的遗留代码,我应该用火杀死它?

它之所以有效,是因为对
CleanFileName(string,int)
的调用是从与
CleanFileName(string)
相同的类型中进行的,这允许以标准方法语法进行调用,而不是扩展方法语法。因此,扩展方法前面不需要字符串实例前缀


从语义上讲,
static string Foo(this string Foo,int bar){}
可以以
Foo(string,int)
string的形式调用。Foo(int)

扩展方法总是可以选择调用,就好像“this”修饰符根本不在那里一样(也称为正常的静态方法)。这样做可读性较差,但在语法上是有效的


另一个答案是误导性的,因为“它之所以有效,是因为方法调用是从与其重载相同的类型中进行的。”这暗示了一些关于扩展方法的内容。您可以像普通静态方法一样调用扩展方法,而不管您在哪个类中。但是通过下面的评论,似乎混淆的是这个班级是否需要资格认证。在这方面,Nathan是正确的,可以省略类名的原因是因为调用与重载发生在同一个类中。

我没有否决它,但答案与您是否从“同一类型内部”调用它无关。我不明白您的意思是什么?这正是答案的意义所在。当答案仅仅是第一句话时,“否决票”是如此的不完整以至于不正确。第二段对此进行了改进,但简单的回答是,可以使用完整的Class.Method语法或通过扩展速记调用扩展方法,类的内部或外部与此无关。扩展方法是一种语法糖,用于以普通方式通过传入所有参数(包括第一个参数)调用静态方法。(事实上,对扩展方法的调用总是编译成一个普通的静态方法调用)@Nathan,这句话是错误的:“它可以工作,因为方法调用是从与重载相同的类型中进行的。”你为什么认为这不应该工作?明确指出,
扩展方法是一种特殊的静态方法,但它们被调用时就好像它们是扩展类型上的实例方法一样。我认为另一个答案“显然是错误的”的说法是不正确的。在类型中,可以调用该类型的静态方法,而无需在方法调用前加上声明类型。因此,在同一类型中,从一个扩展方法到另一个扩展方法的调用没有声明类型前缀,就像其他不是“扩展”的静态声明一样。是的,但问题是,它与您是否“在同一类型中”无关。您可以从任何类型使用该语法因为它是在扩展类之外键入的。在扩展类之外,该方法调用必须以声明类型作为前缀,例如
string.CleanFileName(fileName,64)
或字符串实例,如
mystring.CleanFileName(64)我认为这是OP提出原始问题的意图。Kirk的观点也很正确,它就像任何常规静态方法一样,但我相信OP被弄糊涂了,为什么它可以在没有类名或实例前缀的情况下调用。扩展方法非常酷,但它们的实施方式导致了如此多的混乱。有点遗憾。