C#中的扩展方法

扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。 以上是msdn官网对扩展方法的描述,现在我通过一个情景例子来对此进行阐释。假设一个控制台程序class
Program{}里面的主函数如下:

static void Main(string[] args)
{
DateTime now = DateTime.Now;
string time = now.ToString("yyyy-MM-dd HH:mm:ss");
Console.WriteLine(time);
Console.ReadKey();
}

假设需求变了,日期的显示格式要变成"yyyy-MM-dd"这种格式,当然只需要初始化time时按下面写法改写即可:

string time = now.ToString("yyyy-MM-dd");

但是如果要改变日期格式的有很多个类呢?每个都要改一次吗?这样一旦需求变来变去就忙死人了。传统的解决方式是封装一个帮助类,在里面写方法,然后供其他类调用。

本例在当前项目模仿添加一个DateHelper类:public
class DateHelper{},在类里面定义方法:

public static string DateToString(DateTime dt)
{
return dt.ToString("yyyy-MM-dd HH:mm:ss");
}

于是原来的主函数改写如下:

static void Main(string[] args)
{
DateTime now = DateTime.Now;
string time = DateHelper.DateToString(now);
Console.WriteLine(time);
Console.ReadKey();
}

此时如果变需求,只需要改写DateHelp类里的DateToString()方法就行了,不管有多少个类调用此方法,都会被影响。问题解决了,可是这样要调用另一个类的方法,还是有点麻烦,有没有什么方法能够让我们像now.DateToString()一样直接调用呢?当然DateTime是微软写好的,我们改不了,无法创建想要的实例方法,于是,便引出了扩展方法。
下面是扩展方法的要素:

1.此方法必须是一个静态方法

2.此方法必须放在静态类中

3.此方法的第一个参数必须以this开头,并且指定此方法是扩展自哪个类型

根据以上要素,我们DateHelper类改成静态类:public static class DateHelper{} ,同时改写DateToString()方法:

public static string DateToString(this DateTime dt)
{
return dt.ToString("yyyy-MM-dd HH:mm:ss");
}

此时回到主函数方法体,输入"now."便可以看见自动提示有个DateToString()方法,于是代码可以这样写:

static void Main(string[] args)
{
DateTime now = DateTime.Now;
string time = now.DateToString();
Console.WriteLine(time);
Console.ReadKey();
}

显而易见,这样用起来会更加便捷,而且这样让我们看起来确实就像是被扩展类型本身具有的实例方法一样,可读性很高。下面概括一下扩展方法的特点:

1.扩展方法扩展自哪个类型,就必须是此类型的变量来使用,其他类型无法使用,本例扩展自DateTime类型,就只能是被DateTime类型的变量.出来(now.DateToString())

2.扩展方法中的this后面的参数不属于方法的参数,本例是无参数,this后面的DateTime dt是指明扩展方法扩展自何种类型

3.如果扩展方法和实例方法具有相同的签名,则优先调用实例方法

4.扩展自父类上的方法,可以被子类的对象直接使用

5.扩展自接口上的方法,可以被实现类的对象直接使用

6.扩展方法最终还是被编译器编译成:静态类.静态方法(),本例中now.DateToString()最终还是会被编译成DateHelper.DateToString(now),这是它的本质

实际上,我们可能会遇到这样的情景,如在接口扩展一个方法的时候,所有的原本已实现该接口的类都要实现新扩展的方法,这样的改动是一个很麻烦的工作,可以使用扩展方法“曲线救国”;而有时候我们想为某个类添加新方法却不想改动这个类,那么扩展方法这种“伪添加”方法的方式就体现出它的价值了。最常见的扩展方法是LINQ标准查询运算符,运用广泛,这种方便快捷的方式理应博得码农们点1024个赞。

不逆袭,不 I T !

Can't fly , can't be an IT guy !
转载自:http://www.cnblogs.com/0weibin/p/3954639.html

C#中的扩展方法(向已有类添加方法,但无需创建新的派生类型)的更多相关文章

  1. Groovy中如何向已有的类添加新方法

    Groovy 中有多种途径实现向原有类添加方法,具体有如下几种: MOP(meta object protocol) -- 详见 ExpandoMetaClass 扩展方法 -- GDK采用的此方法 ...

  2. 运行过程中给类添加方法 types.MethodType

    class Person(object): def __init__(self,name = None,age = None): self.name = name#类中拥有的属性 self.age = ...

  3. runtime-给系统已有类添加属性

    在没有接触runtime之前,我们接触到的能给类进行扩展的方法有类目(category)和延展(extension)两种.类目(category)可以给系统已有类添加扩展方法但是不能添加属性,并且被添 ...

  4. Javascript中两种最通用的定义类的方法

    在Javascript中,一切都是对象,包括函数.在Javascript中并没有真正的类,不能像C#,PHP等语言中用 class xxx来定义.但Javascript中提供了一种折中的方案:把对象定 ...

  5. 构造方法概念,自定义构造(init)方法的用途, 类工厂方法(就是直接用类名 类调用)

    一. 构造方法 构造方法:在OC中init开头的方法, 我们称之为构造方法 构造方法的用途: 用于初始化一个对象, 让某个对象一创建出来就拥有某些属性和值 // 比如我们定义一个Person的类,然后 ...

  6. .NET C#利用反射获取类文件以及其中的方法&属性 并获取类及方法上的特性

    了解C#特性类并声明我们自己的特性类[AttributeTest]代码如下 using System; namespace AttributeTest { /* 特性说明 特性本质是一个继承和使用了系 ...

  7. python3 高级编程(二) 动态给类添加方法功能

    class Student(object): pass 给实例绑定一个属性: >>> s = Student() >>> s.name = 'Michael' # ...

  8. [ActionScript3.0] 为内建类添加方法

    通过使用prototype在继承内建类特性的同时加入新方法 Array.prototype.removeElement = function (item:*):void { var index:int ...

  9. 已有使用Key登陆机器,创建新账号并使用新Key登陆

    背景信息:CentOS6.9机器,目前是使用Key进行登陆的,现在需要创建一个新账号并使用新生成的Key进行登陆使用 使用连接Linux工具:XShell 1.在当前机器中创建一个新用户: # use ...

随机推荐

  1. 个人永久性免费-Excel催化剂功能第99波-手机号码归属地批量查询

    高潮过往趋于平静,送上简单的手机号码归属地查询,因接口有数量限制,仅能满足少量数据需求,如有大规模数据却又想免费获得,这就成为无解了,数据有价,且用且珍惜. 业务使用场景 除了日常自带的手机各种管家为 ...

  2. 个人永久性免费-Excel催化剂功能第37波-把Sqlserver的强大分析函数拿到Excel中用

    本人一直钟情于使用Sqlserver数据库的一大原因是其提供了非常好用.高效的数据分析函数(窗口函数),可以在做数据清洗和数据分析场合等多个场景使用.只需简单的一个函数即可做出常规SQL语句很难以实现 ...

  3. Git学习(一):版本控制介绍及安装

    一.VCS(版本控制系统)的演变 1.集中式VCS的特点 1)有集中的版本管理服务器: 2)具备文件版本管理和分支管理能力: 3)集成效率较没有版本控制(如:进行文件夹标注的方式)有明显地的提高: 4 ...

  4. Maven国内镜像 Maven阿里云镜像

    <mirror> <id>nexus-aliyun</id> <mirrorOf>central</mirrorOf> <name&g ...

  5. python基础——字典(dict)

    字典是另一种可变容器模型,且可存储任意类型对象. 字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中 . dict1 = {} ...

  6. php的中文字符

    在使用substr截取字符窜的时候出现乱码的问题 一直任认为字符串是2个字节,直到多次才尝试才总算知道问题所在 php的utf-8字符是每个字符3个字节 而gbk字符是每个字节2个字符 单个字母和符号 ...

  7. 【CocoaPods】ERROR: While executing gem ... Gem::DependencyError

    今天安装 CocoaPods 时遇到了这个问题. ERROR: While executing gem ... (Gem::DependencyError) Unable to resolve dep ...

  8. iOS 注释

    1) 参数的注释: UIButton *btnSend;/**< 发送按钮 */ 效果: 2) 方法的注释: type1(无参数): /** table 相关设置 */ -(void)confi ...

  9. Python—三目运算

    Python 可通过 if 语句来实现三目运算的功能,因此可以近似地把这种 if 语句当成三目运算符.作为三目运算符的 if 语句的语法格式如下: (True_statements) if (expr ...

  10. 动态开内存(malloc与calloc)

    malloc与calloc 1.函数原型 #include<stdlib.h> void *malloc(unsigned int size);     //申请size字节的内存 voi ...