函数参数中的"this"

chr*_*ris 79 c# parameters asp.net-mvc

看一下HtmlHelpers的一些代码示例,我看到的声明如下:

public static string HelperName(this HtmlHelper htmlHelper, ...more regular params )
Run Code Online (Sandbox Code Playgroud)

我不记得在其他地方看到过这种类型的构造 - 有人可以解释"这个"的目的吗?我认为通过声明一些公共静态意味着该类不需要实例化 - 所以在这种情况下什么是"this"?

ang*_*son 196

这是声明扩展方法的语法,扩展方法是C#3.0的一个新特性.

扩展方法是部分代码,部分编译器"魔术",其中编译器在Visual Studio中使用intellisense使得看起来您的扩展方法实际上可用作相关对象的实例方法.

让我举个例子.

String类上没有名为GobbleGobble的方法,所以让我们创建一个扩展方法:

public static class StringExtensions
{
    public static void GobbleGobble(this string s)
    {
        Console.Out.WriteLine("Gobble Gobble, " + s);
    }
}
Run Code Online (Sandbox Code Playgroud)

类名只是我的命名约定,没有必要像这样命名,但它必须是静态的,方法也是如此.

声明上述方法后,您可以在Visual Studio中键入以下内容:

String s = "Turkey Baster!";
s.
Run Code Online (Sandbox Code Playgroud)

在点之后,等待intellisense,并注意到那里有一个GobbleGobble方法,完成如下代码:

String s = "Turkey Baster!";
s.GobbleGobble();
Run Code Online (Sandbox Code Playgroud)

要点:声明扩展方法的类必须可供编译器和智能感知处理器使用,以便intellisense显示该方法.如果您手动输入GobbleGobble并使用Ctrl+ .快捷键,则无法帮助您在文件中使用指令.

请注意,方法的参数已消失.编译器将默默地移动重要位,这些位是:

String s = "Turkey Baster!";
s.GobbleGobble();
^     ^
|     +-- the compiler will find this in the StringExtensions class
|
+-- will be used as the first parameter to the method
Run Code Online (Sandbox Code Playgroud)

因此,上面的代码将由编译器转换为:

String s = "Turkey Baster!";
StringExtensions.GobbleGobble(s);
Run Code Online (Sandbox Code Playgroud)

所以在通话时,它并没有什么神奇之处,它只是对静态方法的调用.

请注意,如果您的扩展方法声明了多个参数,则只有第一个支持this修饰符,其余的必须作为方法调用的一部分指定为正常:

public static void GobbleGobble(this string value, string extra)
{                                            |              |
    ...                                      |              |
}                                            |              |
                                             |              |
+--------------------------------------------+              |
|                                                           |
v                                                           |
s.GobbleGobble("extra goes here");                          |
                        ^                                   |
                        |                                   |
                        +-----------------------------------+
Run Code Online (Sandbox Code Playgroud)

扩展方法部分归因于Linq,其中C#的Linq语法将为正在使用的对象寻找适当命名的扩展方法,这意味着只需声明正确的扩展即可将Linq-support"引入"任何类型的类中方法.当然,完整的Linq支持是很多工作,但它是可能的.

此外,扩展方法本身非常有用,所以请阅读它.

这里有几个链接:

  • 我肯定会开始使用"Gobble Gobble Magic"这个词. (5认同)
  • 这些编译器的魔力让学习一门语言变得困难。 (5认同)

jae*_*kie 7

在扩展方法之后,我一直在疯狂地使用它们.这里有一些我经常使用的..

public static T ChangeType<T>(this object obj)
{
  return (T)Convert.ChangeType(obj, typeof(T));
}
Run Code Online (Sandbox Code Playgroud)

像这样工作..

int i = "123".ChangeType<int>();
bool valid = "bool".ChangeType<bool>();
int id = dataSet.Tables[0].Rows[0]["Id"].ChangeType<int>();
Run Code Online (Sandbox Code Playgroud)

是的,它显示在每个单独的对象上,可能很烦人,但由于我几乎每种数据类型都使用它,因此只需将对象附加到对象而不是为每种可能的数据类型复制它.

public static string ToXml(this object serializableObject)
{
    var aMemStr = new MemoryStream();
    try
    {
        var serializer = new XmlSerializer(serializableObject.GetType());
        serializer.Serialize(new XmlTextWriter(aMemStr, null), serializableObject);
        return Encoding.UTF8.GetString(aMemStr.ToArray());
    }
    finally { if (aMemStr != null) { aMemStr.Dispose(); } }
}

string xml = dataSet.ToXml();

public static T ToObject<T>(this string xmlString)
{
    var aStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString));
    try { return (T)new XmlSerializer(typeof(T)).Deserialize(aStream); }
    finally { if (aStream != null) { aStream.Dispose(); aStream = null; } }
}

DataSet dataSet = xml.ToObject<DataSet>();
Run Code Online (Sandbox Code Playgroud)


Hen*_*ing 6

它用于扩展方法.基本上你将Helpername"粘合"到htmlHelper对象,这样你就可以说:

new HtmlHelper().HelperName(...more regular params);
Run Code Online (Sandbox Code Playgroud)


Jus*_*ner 5

那将是一个扩展方法。它们允许您通过位于原始类之外的静态方法“扩展”一个类。

例如,假设您有一个一直在使用的有用字符串方法......

public int CountAllAs(string orig)
{
    return orig.ToLowerInvariant().ToArray().Count(c => c == 'a');
}
Run Code Online (Sandbox Code Playgroud)

而你称之为...

string allAs = "aaaA";
int count = CountAllAs(allAs);
Run Code Online (Sandbox Code Playgroud)

这还不错。但是只要稍作改动,您就可以将其设置为 Extension 方法,并且调用会更漂亮一点:

public static int CountAllAs(this string orig)
{
    return orig.ToLowerInvariant().ToArray().Count(c => c == 'a');
}
Run Code Online (Sandbox Code Playgroud)

然后叫它...

string allAs = "aaaA";
int count = allAs.CountAllAs();
Run Code Online (Sandbox Code Playgroud)