在 OOPL 中,有静态方法、实例方法和虚方法,如下:
 
public sealed class String
{
     public static bool  IsNullOrEmpty(string s)
     {
          // ...
     }
 
     public string Replace(string old, string new)
     {
          // ...
     }
}
public abstract class Stream
{
     public virtual void WriteByte(byte value)
     {
          // ...
     }
}
 
其中,IsNullOrEmpty 是静态方法,Replace 是实例方法,而 WriteByte 就是虚方法。其用法如下:
 
String name = null;
Console.WriteLine(String.IsNullOrEmpty(name));      // true
 
String s = "Hello, world!";
Console.WriteLine(s.Replace("world", "C#"));          // Hello, C#!
 
虚方法需要在导出类(derived class)中重新定义,此处不赘。
 
而在 C# 3.0 中,又引入了一种方法,称为 扩展方法(Extension Method):
 

Extension methods allow an exsting type to be extended with new methods without altering the definition of the original type.

扩展方法是用新方法来扩展原有类型,而不用修改原有类型的定义。
 
扩展原有类型(Extending the existing type)
 
扩展原有类型的机制(手段)有类的继承,还有 C# 中的扩展方法。
 
类的继承通过增加新成员,可以扩展原有类型的数据成员(fields);可以定义新方法或重写被继承类的虚方法来扩展原有类型的方法成员(methods)。但继承机制也存在自己的问题,如果原有类型声明为封闭类型(sealed class),则无法使用继承机制扩展原有类型(如上述的 String class)。再者,导出类(derived class)对基类(base class)的扩展是作用在导出类上的,而非对基类自身的扩展。
 
扩展方法弥补了继承机制的不足。严格说来,扩展方法不是语言本身的机制,而是通过编译程序实现的语法便用设施。不管原有类型是封闭类型还是开放类型,都可以用扩展方法进行扩展。扩展方法只是扩展原有类的方法成员,并不能扩展原有类的数据成员。
 
An extension method is a static method of a static class, where the this modifier is applied to the first parameter. The type of the first parameter will be the type that is extended.
扩展方法是静态类的静态方法,其第一个参数要用 this 修饰,而这第一个参数的类型就是要扩展的类型。
 
例子:
 
public static class StringHelper
{
     public static bool IsCapitalized(this string s)
     {
          if (string.IsNullOrEmpty(s)) return false;
          return char.IsUpper(s[0]);
     }
}
 
IsCapitalized 就是定义在静态类上的静态方法,而其第一个参数 string s 用 this 修饰,所以 IsCapitalized 是扩展方法,因为第一个参数的类型是 string,所以 IsCapitalized 扩展的是 string 类型。
 
用法:
 
Console.WriteLine("Perth".IsCapitalized());
 
"Perth".IsCapitalized() 是直接针对 string "Perth" 调用 IsCapitalized(),因为 IsCapitalized() 是 string 的扩展方法,所以这种调用是可以的。
 
扩展方法的调用经过编译器的解析后,就翻译为普通的静态方法调用,即:
 
Console.WriteLine(StringHelper.IsCapitalized("Perth"));
 
而 "Perth".IsCapitalized() 相对于 StringHelper.IsCapitalized("Perth") 而言,更为自然、简洁。
 
所以,扩展方法仍然是一种静态方法,只是 C# 语言引入的语法便用设施而已。编译器的翻译过程如下:
 
     arg0.Method(arg1, arg2, ...);  ==> StaticClass.Method(arg0, arg1, arg2, ...);
 
也就是将扩展方法调用翻译为普通的静态方法调用。
 
扩展方法的应用
 
string 类虽然提供了功能强大的众多方法,但总是不可能满足所有需求。有些经常使用而 string 类又没有提供的功能,可以写成扩展方法,并归入代码库(Library),可以再多个项目中使用。下面是一个例子,两个有关 string 的扩展方法,放入 StringExtensions 类中:
 
    public static class StringExtensions
    {
        public static List<KeyValuePair<string, string>> Listize(this string ss)
        {
            List<KeyValuePair<string, string>> pList = new List<KeyValuePair<string, string>>();
            string[] slist = ss.Split(new char[] { ';' });
            foreach (string s in slist)
            {
                if (string.IsNullOrEmpty(s)) continue;
                string[] pair = s.Split(new char[] { ':' });
                if (pair.Length != 2) continue;
                pList.Add(new KeyValuePair<string, string>(pair[0], pair[1]));
            }
            return pList;
        }
        public static string MatchAndReplace(this string src, string pattern, string dst)
        {
            List<string> mList = new List<string>();
            foreach (Match m in Regex.Matches(src, pattern))
            {
                mList.Add(m.Value);
            }
            foreach (string s in mList)
            {
                if (string.IsNullOrEmpty(s)) continue;
                src = src.Replace(s, dst);
            }
            return src;
        }
    }
 
上述两个扩展方法的用例如下:
 
    string sql = GetSQL();
    string whereTail = "";
    foreach (string k in po.CustomObject.Keys)
    {
        if (string.IsNullOrEmpty(k)) continue;
        if (string.Compare(k, "DemoZoneList", true) == 0)
        {
            whereTail = po.CustomObject[k].Value.Listize().BuildWhereClauseInclusive();
        }
        else if (string.Compare(k, "NonDemoZoneList", true) == 0)
        {
            whereTail = po.CustomObject[k].Value.Listize().BuildWhereClauseExclusive();
        }
    }
    if (!string.IsNullOrEmpty(whereTail))
    {
        sql = sql.MatchAndReplace("1[ ]*=[ ]*1", whereTail);
    }
 
可以看到,string 的扩展方法就像原生方法(指 String 类定义的方法)一样调用,代码看起来更加自然、简洁。
 
扩展方法机制是为了解决 LINQ 的问题而引入的,关于这一点,当另文别述。关于扩展方法的深入讨论,可以参阅《C# in Depth》 Third Edition。
 
 

Extension Methods(扩展方法)的更多相关文章

  1. [C#] Extension Method 扩展方法

    当我们引用第三方的DLL.或者Visual Studio自己的库的时候,或许会发现这样的一个情况,如果这个类型有一个XX的方法就好了.这时候我们可以用到扩展方法,是我们的代码更加灵活和高效. 这里我举 ...

  2. C# Extension Methods(C#类方法扩展)

    使用Extension methods 可以在已有的类型(types)中添加方法(Methods),而无需通过增加一种新的类型或修改已有的类型. 比如说,想要给string类型增加一个PrintStr ...

  3. C# -- 扩展方法的应用(Extension Methods)

    当你有下面这样一个需求的时候,扩展方法就会起到作用:在项目中,类A需要添加功能,我们想到的就是在类A中添加公共方法,这个显而易见肯定可以,但是由于某种原因,你不能修改类A本身的代码,但是确实又需要增加 ...

  4. (转)C# -- 扩展方法的应用(Extension Methods)

    本文转载自:http://blog.csdn.net/zxz414644665/article/details/9793205 当你有下面这样一个需求的时候,扩展方法就会起到作用:在项目中,类A需要添 ...

  5. Extension Methods "点"函数方法 扩展方法

    原文发布时间为:2011-03-25 -- 来源于本人的百度文章 [由搬家工具导入] http://msdn.microsoft.com/en-us/library/bb383977.aspx 条件: ...

  6. C# Note21: 扩展方法(Extension Method)及其应用

    前言 今天在开会时提到的一个概念,入职3个多月多注重在项目中使用C#的编程知识,一直没有很认真地过一遍C#的全部语法,当我们新人被问及是否了解Extension Method时,一时之间竟不能很通俗准 ...

  7. [译文]c#扩展方法(Extension Method In C#)

    原文链接: https://www.codeproject.com/Tips/709310/Extension-Method-In-Csharp 介绍 扩展方法是C# 3.0引入的新特性.扩展方法使你 ...

  8. [0] C# 扩展方法(Extension Method)

    有时有这样的情况,有一个类,你不能修改它,但你又想对它扩展(添加一个方法),这个时候就可以用到扩展方法了.请看下面的例子: using System;using System.Collections. ...

  9. c#编程指南(五) 扩展方法(Extension Method)

    C# 3.0就引入的新特性,扩展方法可以很大的增加你代码的优美度,扩展方法提供你扩展.NET Framewoke类的扩展途径,书写和规则也简单的要命. 编写扩展方法有下面几个要求: 第一:扩展方法所在 ...

随机推荐

  1. angular中多个promise的合并处理

    all()方法 这个all()方法,可以把多个primise的数组合并成一个.当所有的promise执行成功后,会执行后面的回调.回调中的参数,是每个promise执行的结果.当批量的执行某些方法时, ...

  2. python爬取数据保存到Excel中

    # -*- conding:utf-8 -*- # 1.两页的内容 # 2.抓取每页title和URL # 3.根据title创建文件,发送URL请求,提取数据 import requests fro ...

  3. Spring @Conditional注解 详细讲解及示例

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/xcy1193068639/article/details/81491071 前言: @Conditi ...

  4. [洛谷P1114] “非常男女”计划

    题目描述 近来,初一年的XXX小朋友致力于研究班上同学的配对问题(别想太多,仅是舞伴),通过各种推理和实验,他掌握了大量的实战经验.例如,据他观察,身高相近的人似乎比较合得来. 万圣节来临之际,XXX ...

  5. jQuery通过event获取点击事件的事件对象

    要想搞明白js的事件机制,必须搞清楚几个概念:事件对象,事件源,还有事件流 事件对象: 当事件发生时会产生事件对象,事件对象的作用是用来记录“事件发生是一些相关的信息.注意事件对象只有在事件发生时才会 ...

  6. 这个函数有搞头,要调试通过就差不多啦--ImpersonateActiveUserAndRun

    //Function to run a process as active user from windows service void ImpersonateActiveUserAndRun() { ...

  7. MVC模式利用xib文件定制collectionCell

    数据来源于豆瓣网~仅供学习交流~ 本实例练习用到了SDWebImage框架:实现从网络端下载图片的功能 下载地址:https://github.com/rs/SDWebImage 实现效果及框架: x ...

  8. JS执行环境栈及事件循环机制—简洁明了的讲解

    JavaScript解释器在浏览器中是单线程的,这意味着浏览器在同一时间内只执行一个事件,对于其他的事件我们把它们排队在一个称为 执行栈(调用栈) 的地方.下表是一个单线程栈的抽象视图: 我们已经知道 ...

  9. Java 实现抽象工厂模式

    抽象工厂模式 里面有几个概念:抽象工厂.实体工厂.抽象产品.实体产品 抽象工厂:定义创建产品的抽象方法 实体工厂:详细的创建哪种产品 抽象产品:一个接口或基类 实体产品:实现详细功能,或派生 类图 ...

  10. BZOJ 3007 解救小云公主 二分答案+对偶图

    题目大意:给定一个矩形和矩形内的一些点.求一条左下角到右上角的路径.使全部点到这条路径的最小距离最大 最小距离最大.果断二分答案 如今问题转化成了给定矩形中的一些圆形障碍物求左下角和右上角是否连通 然 ...