代码之家  ›  专栏  ›  技术社区  ›  chris

函数参数中的“this”

  •  74
  • chris  · 技术社区  · 15 年前

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

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

    我不记得在其他地方见过这种类型的构造-有人能解释“这个”的目的吗?我认为声明publicstatic意味着类不需要实例化——那么在这种情况下“this”是什么呢?

    5 回复  |  直到 15 年前
        1
  •  219
  •   Lasse V. Karlsen    15 年前

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

    扩展方法是部分代码,部分编译器“magic”,其中编译器在visualstudio中借助intellisense使您的扩展方法看起来实际上可以作为所讨论对象的实例方法使用。

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

    类名只是我的命名约定,不必这样命名,但它必须是静态的,方法也是静态的。

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

    String s = "Turkey Baster!";
    s.
    

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

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

    重要 :声明扩展方法的类必须对编译器和intellisense处理器可用,以便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
    

    因此,编译器将上述代码转换为:

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

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

    this 修饰符,其余部分必须作为方法调用的一部分指定为普通:

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

        2
  •  8
  •   jaekie    15 年前

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

    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>();
    
        3
  •  6
  •   Henrik Gering    15 年前

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

    new HtmlHelper().HelperName(...more regular params);
    
        4
  •  5
  •   Justin Niessner    15 年前

    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();
    
        5
  •  3
  •   Fraga    15 年前

    Extensions Methods

    …是包含功能的绝佳方式,例如 decorator pattern ,但无需对所有代码进行重构,或使用公共类型的不同名称。

    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
    

    所以 command属性表示将添加扩展的类型,并允许您处理该值,就好像它是作为参数传递的一样。