在C#中,静态方法的形式参数中使用"this"关键字的用法

364

我遇到了几个类似以下C#代码的实例:

public static int Foo(this MyClass arg)

我找不到关于this关键字在这种情况下的解释。有什么见解吗?


11
除了已接受的答案,对于 C# 扩展方法,必须查看官方的MSDN 文档 - vulcan raven
5
扩展方法很方便,但我们在创建/使用它们时必须小心 - 它们可能会出现问题!引用来自官方MSDN文档中的总体指导:“通常情况下,我们建议您谨慎实现扩展方法,并仅在必要时使用。...当使用扩展方法扩展源代码无法更改的类型时,您面临的风险是类型实现的更改会导致您的扩展方法出现问题。” - Krishna Gupta
这是否意味着这个是可能的?因为这就是我正在寻找的。 - mekb
8个回答

339
这是一个扩展方法。在这里可以查看说明
扩展方法允许开发人员向现有CLR类型的公共契约添加新方法,而无需对其进行子类化或重新编译原始类型。扩展方法帮助将“鸭子类型”支持的灵活性与强类型语言的性能和编译时验证相结合。扩展方法实现了各种有用的场景,并帮助实现了功能强大的LINQ查询框架……
这意味着您可以调用它。
MyClass myClass = new MyClass();
int i = myClass.Foo();

与其

MyClass myClass = new MyClass();
int i = Foo(myClass);

如下所述,这允许构建流畅接口(fluent interfaces)


子类化很难。 - Gerry
@Gerry - 你是什么意思? - Preet Sangha
27
抱歉,有点讽刺 - 最近很多语法似乎解决了我甚至不知道存在的问题。阅读易懂应该是非常重要的优先事项。 - Gerry
7
老实说 @Gerry,听起来你的情况有点像经典的布鲁布悖论。现在很多语法解决了你没有遇到过的问题,因为你不知道有更好的方法,或者你不是做这种语法特别适合的任务。关于“这是一种解决不了问题的解决方案”的大部分评论实际上是“我不知道那个功能是怎么工作的,所以它肯定没用”的例子。 - Myrddin Emrys

96

Scott Gu所引用的博客文章很好地解释了这一点。

对我来说,这个问题的答案在该文章的以下陈述中:

请注意上面的静态方法有一个“this”关键字, 在第一个类型为字符串的参数之前。这告诉编译器, 应将此特定扩展方法添加到“string”类型的对象中。 在IsValidEmailAddress()方法实现中, 我可以访问调用该方法的实际字符串实例的所有公共属性/方法/事件, 并根据其是否有效电子邮件返回true/false。


22
这应该是被接受的答案。它是唯一一个真正解释了方法签名中 this 关键字实际用途的答案。其他的回答只是不太有用地说“这是扩展方法”。在阅读了这个答案之前,我从未完全理解扩展方法如何“附加”到它们扩展的类型上。谢谢! - Lews Therin

14

如果你可以整洁地弹出一个List<>,那不是很方便吗?也就是说,不仅删除第一个元素,而且还要返回它。

List<int> myList = new List<int>(1, 2, 3, 4, 5);

没有扩展方法:

public static class ContainerHelper
{
    public static T PopList<T>(List<T> list)
    {
        T currentFirst = list[0];
        list.RemoveAt(0);
        return currentFirst;
    }
}

调用这个方法:

int poppedItem = ContainerHelper.PopList(myList);

使用扩展方法:

public static class ContainerHelper
{
    public static T PopList<T>(this List<T> list)//Note the addition of 'this'
    {
        T currentFirst = list[0];
        list.RemoveAt(0);
        return currentFirst;
    }
}

调用此方法:
int poppedItem = myList.PopList();

12

除了Preet Sangha的解释外:
Intellisense会显示带有蓝色箭头的扩展方法(例如在"Aggregate<>"前面):

enter image description here

您需要

using the.namespace.of.the.static.class.with.the.extension.methods;
为了让扩展方法出现并可用,即使它们在与使用它们的代码不同的命名空间中。

7

5

我最近学到了这个知识:this关键字定义了该方法作为其前面类的扩展。因此,对于您的示例,MyClass将具有一个名为Foo的新扩展方法(它不接受任何参数并返回一个int;可以像其他公共方法一样使用)。


1
"

"this"扩展了参数列表中的下一个类。

因此,在下面的方法签名中,“this”扩展了“String”。Line作为普通参数传递给该函数的方法。

在上面的示例中,“this”类扩展了内置的“String”类。

"

-1
在参数前使用修饰符"this",是关于扩展方法的用法。
更详细的解释和示例,请参阅我的CSDN博客。

http://t.csdn.cn/QYeW6


好的做法是在链接旁边分享内容或摘要。外部链接可能会被更改或删除。 - KargWare

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