“这个”在函数参数中

发布于 2025-01-09 10:01:18 字数 256 浏览 0 评论 0原文

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

public static string HelperName(this HtmlHelper htmlHelper, ...more regular params )

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

Looking at some code examples for HtmlHelpers, and I see declarations that look like this:

public static string HelperName(this HtmlHelper htmlHelper, ...more regular params )

I can't remember seeing this type of construct anywhere else - can someone explain the purpose of the "this"? I thought that by declaring something public static meant that the class did not need to be instantiated - so what is "this" in this case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

饮惑 2025-01-16 10:01:18

这是声明扩展方法的语法,是 C# 3.0 的新功能。

扩展方法部分是代码,部分是编译器“魔法”,其中编译器在 Visual Studio 中的智能感知的帮助下,使您的扩展方法实际上可以作为相关对象的实例方法使用。

让我举个例子。

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

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

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

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

String s = "Turkey Baster!";
s.

在点后,等待智能感知,并注意那里有一个 GobbleGobble 方法,完成如下代码:

String s = "Turkey Baster!";
s.GobbleGobble();

重要:类其中声明的扩展方法必须可供编译器和智能感知处理器使用,以便智能感知显示该方法。如果您手动输入 GobbleGobble,并使用 Ctrl+. 快捷键,它不会帮助您在文件中获得正确的 using 指令。

请注意,该方法的参数已消失。编译器将悄悄地移动重要的位,它们是:

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

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

String s = "Turkey Baster!";
StringExtensions.GobbleGobble(s);

因此在调用时,它没有什么神奇的,它只是对静态方法的调用。

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

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

添加扩展方法的部分原因是到 Linq,其中 C# 的 Linq 语法将为正在使用的对象查找适当命名的扩展方法,这意味着您只需声明正确的扩展方法即可将 Linq 支持“引入”到任何类型的类中。当然,完整的 Linq 支持需要大量工作,但这是可能的。

另外,扩展方法本身非常有用,所以请仔细阅读。

以下是一些链接:

This is the syntax for declaring extension methods, a new feature of C# 3.0.

An extension method is part code, part compiler "magic", where the compiler with the help of intellisense in Visual Studio make it appear that your extension method is actually available as an instance method on the object in question.

Let me give an example.

There's no method on the String class that is named GobbleGobble, so let's create an extension method:

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

The class name is just my naming convention, it isn't necessary to name it like that, but it has to be static, as do the method.

After declaring the above method, you can, in Visual Studio, type this:

String s = "Turkey Baster!";
s.

after the dot, wait for intellisense, and notice there is a GobbleGobble method there, complete the code like this:

String s = "Turkey Baster!";
s.GobbleGobble();

Important: The class where the extension method is declared must be available to the compiler and the intellisense processor in order for intellisense to show the method. If you type in GobbleGobble manually, and use the Ctrl+. shortcut, it will not help you get the right using directives into the file.

Notice that the parameter to the method has disappeared. The compiler will silently move around the important bits, which are:

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

Thus, the above code will be transformed by the compiler to this:

String s = "Turkey Baster!";
StringExtensions.GobbleGobble(s);

So at call-time, there's nothing magical about it, it's just a call to a static method.

Note that if your extension method declares more than one parameter, only the first supports the this modifier, and the rest has to be specified as part of the method call as normal:

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

Extension methods was added in part due to Linq, where the Linq syntax of C# will look for appropriately named extension methods for the objects in play, which means you can "introduce" Linq-support into any type of class by just declaring the right extension methods. Of course, full Linq support is a lot of work, but it is possible.

Also, extension methods by themselves are really useful, so read up on it.

Here's a few links:

一梦浮鱼 2025-01-16 10:01:18

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

public static T ChangeType<T>(this object obj)
{
  return (T)Convert.ChangeType(obj, typeof(T));
}

像这样工作..

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

是的,它出现在每个对象上,可能很烦人,但因为我几乎在每个对象上都使用它数据类型,它有助于将其附加到一个对象,而不是为每种可能的数据类型复制它。

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>();

After extension methods, I've been using them like crazy.. here is a few I use constantly..

public static T ChangeType<T>(this object obj)
{
  return (T)Convert.ChangeType(obj, typeof(T));
}

Works like this..

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

Yeah, it shows up on every single object, can be annoying but since I use this for pretty much every data type, it helps to just attach it an object rather than duplicating it for every data type possible.

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>();
茶色山野 2025-01-16 10:01:18

它用于扩展方法。基本上,您将 Helpername “粘合”到 htmlHelper 对象,这样您就可以说:

new HtmlHelper().HelperName(...more regular params);

It is used for extensionmethods. Basically you 'glue' the Helpername to the htmlHelper object so you can say:

new HtmlHelper().HelperName(...more regular params);
小傻瓜 2025-01-16 10:01:18

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

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

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

并且您调用它...

string allAs = "aaaA";
int count = CountAllAs(allAs);

这还不错。但是通过一个小的改变,您可以将其设为扩展方法,并且调用会更漂亮:

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

然后调用它...

string allAs = "aaaA";
int count = allAs.CountAllAs();

That would be an Extension Method. They allow you to "extend" a class via static methods that live outside the original class.

For example, say you have a helpful string method that you use all the time...

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

And you call it...

string allAs = "aaaA";
int count = CountAllAs(allAs);

That's not too bad. But with a small change, you could make it an Extension method and the call would be a little prettier:

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

And then call it...

string allAs = "aaaA";
int count = allAs.CountAllAs();
薄荷港 2025-01-16 10:01:18

扩展方法...

...是包含的绝佳方式功能就像您使用装饰器模式,但没有重构的痛苦您的所有代码,或使用常见类型的不同名称。

public static class Extensions
{
     public static string RemoveComma(this string value)
     {
         if (value == null) throw new ArgumentNullException("value");
        return value.Replace(",", "");
    }
}  

因此,您可以在应用程序中的任何位置使用此代码。

Console.WriteLine(“Hello, My, Friend”.RemoveComma())

>> Hello My Friend

因此,this 命令属性表示扩展将被“添加”的类型,并让您可以像将其作为参数传递一样使用该值。

Extensions Methods...

...are a fantastic way to include functionality like if you where using the decorator pattern, but without the pain of refactoring all your code, or using a different name of a common type.

public static class Extensions
{
     public static string RemoveComma(this string value)
     {
         if (value == null) throw new ArgumentNullException("value");
        return value.Replace(",", "");
    }
}  

So you can use this code, anywhere in you app.

Console.WriteLine(“Hello, My, Friend”.RemoveComma())

>> Hello My Friend

So the this command attribute mean the type that the extension will be “added”, and let you work with the value as if it was passed as parameter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文