扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。这是msdn的描述。上面几句我看好多博客都是这样开头的。所以我也这样开头。

原本想着上一篇博客回顾了下泛型,将具体的模糊化,这个应该讲反射,将模糊的具体化,不过呢看了下反射东西不少,一晚上我也总结不完,还要留点时间打飞机呢。于是想了想就总结下扩展吧。

一、为什么要有扩展方法?

开头也说了,无需创建新的派生类型、重新编译或其他方式修改原始类型给现有类或接口添加方法。比如在没有扩展之前,会经常有一些helper工具类,例如处理字符串、时间的。有了扩展我们可以直接扩展字符串类或时间类就可以了,这样不用在实例化helper类就能直接处理。

二、扩展方法有什么特征?

扩展方法是静态方法,是类的一部分,但是实际上没有放在类的源代码中。
扩展方法所在的类也必须被声明为static
C#只支持扩展方法,不支持扩展属性、扩展事件等。
扩展方法的第一个参数是要扩展的类型,放在this关键字的后面,this后面的参数不属于方法的参数
在扩展方法中,可以访问扩展类型的所有公共方法和属性。
扩展方法扩展自哪个类型,就必须是此类型的变量来使用,其他类型无法使用
如果扩展方法和实例方法具有相同的签名,则优先调用实例方法
扩展自父类上的方法,可以被子类的对象直接使用
扩展自接口上的方法,可以被实现类的对象直接使用
扩展方法最终还是被编译器编译成:静态类.静态方法()

三、demo

上面几句基本总结把扩展总结完了,下面做一个demo来说明一下。

1.定义IAnimal接口 声明void Eat();方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ExtensionMethod
{
public interface IAnimal
{
void Eat();
}
}

2.定义Person类实现接口IAnimal实现void Eat();方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ExtensionMethod
{
public class Person:IAnimal
{
public void Eat()
{
Console.WriteLine("Person Eat");
}
}
}

3.定义扩展方法ExtensionMethod

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ExtensionMethod
{
public static class ExtensionMethod
{
public static void Eat(this IAnimal iAnimal)
{
Console.WriteLine("IAnimalExtension Eat");
}
public static void Sleep(this IAnimal iAnimal)
{
Console.WriteLine("IAnimalExtension Sleep");
}
public static void Eat(this Person person)
{
Console.WriteLine("PersonExtension Eat");
}
public static void Sleep(this Person person)
{
Console.WriteLine("PersonExtension Sleep");
}
} }

上面在ExtensionMethod类中定义了4个扩展方法,两个是对接口IAnimal的扩展,两个是对Person类的扩展。

4.实例化测试

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ExtensionMethod
{
class Program
{
static void Main(string[] args)
{
IAnimal p = new Person();
p.Eat();
p.Sleep();
Console.WriteLine("----------------这是底线------------------------");
Person p1 = new Person();
p1.Eat();
p1.Sleep();
Console.WriteLine("----------------这是底线------------------------"); ExtensionMethod.Eat(p);
ExtensionMethod.Sleep(p);
Console.WriteLine("----------------这是底线------------------------");
ExtensionMethod.Eat(p1);
ExtensionMethod.Sleep(p1);
Console.ReadLine();
}
}
}

上面Mian方法中,首先实例化了一个Person对象,赋值给IAnimal类型的变量,调用Eat()和Sleep()方法。然后又实例化了一个Person对象,这次赋值给Person类型的变量。

下面来看下运行结果是不是出乎意料:

p和p1我们可以对比着来分析,对于Eat()方法都是输出"Person Eat",如果扩展方法和实例方法具有相同的签名,则优先调用实例方法,这句话正好能解释为什么。但是对于Sleep()方法,我们可以看到使用IAnimal类型的变量调用的是接口的扩展方法,使用Person类型的变量调用的是Person类型的扩展方法。扩展方法扩展自哪个类型,就必须是此类型的变量来使用,其他类型无法使用,与这句虽然有点出入,但也是蛮符合的。我是这样理解的:对于同名方法,实例方法优先扩展方法,自身扩展方法优先父类方法。 也可能是因为子类覆盖了父类的扩展方法。

我们可以把Person对的扩展方法注释,然后看下运行结果。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ExtensionMethod
{
public static class ExtensionMethod
{
public static void Eat(this IAnimal iAnimal)
{
Console.WriteLine("IAnimalExtension Eat");
}
public static void Sleep(this IAnimal iAnimal)
{
Console.WriteLine("IAnimalExtension Sleep");
}
//public static void Eat(this Person person)
//{
// Console.WriteLine("PersonExtension Eat");
//}
//public static void Sleep(this Person person)
//{
// Console.WriteLine("PersonExtension Sleep");
//}
} }

从上面的结果可以看到,扩展自接口上的方法,可以被实现类的对象直接使用,其实扩展自父类上的方法,可以被子类的对象直接使用和接口类似

C#语法之扩展的更多相关文章

  1. Swift2.1 语法指南——扩展

    原档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programmi ...

  2. C#语法糖: 扩展方法(常用)

    今天继续分享C#4.0语法糖的扩展方法,这个方法也是我本人比较喜欢的方法.大家先想想比如我们以前写的原始类型不能满足现在的需求,而需要在该类型中添加新的方法来实现时大家会怎么做.我先说一下我没有学习到 ...

  3. 学习php语法--数据库扩展(总结篇)

      前  言  php  php中的数据库扩展mysql语法--本篇学习都是通过使用数字天堂的HBuider开发环境,连接mysql数据.介绍php连接mysql数据库的代码与函数. 本篇学习主要有两 ...

  4. Objective-C语法之扩展(Extension)的使用

    Objective-C 2.0增加了Class Extension用于解决两个问题: 可声明私有可读写的属性,而在类的声明中是同名的公开只读属性,从而来支持公开只读.私有可读写的属性 可声明私有方法: ...

  5. ExtJs4 笔记(2) ExtJs对js基本语法扩展支持

    本篇主要介绍一下ExtJs对JS基本语法的扩展支持,包括动态加载.类的封装等. 一.动态引用加载 ExtJs有庞大的类型库,很多类可能在当前的页面根本不会用到,我们可以引入动态加载的概念来即用即取.这 ...

  6. ExtJs对js基本语法扩展支持

    ExtJs对js基本语法扩展支持 本篇主要介绍一下ExtJs对JS基本语法的扩展支持,包括动态加载.类的封装等. 一.动态引用加载 ExtJs有庞大的类型库,很多类可能在当前的页面根本不会用到,我们可 ...

  7. [转载]ExtJs4 笔记(2) ExtJs对js基本语法扩展支持

    作者:李盼(Lipan)出处:[Lipan] (http://www.cnblogs.com/lipan/) 本篇主要介绍一下ExtJs对JS基本语法的扩展支持,包括动态加载.类的封装等. 一.动态引 ...

  8. 一些Markdown扩展语法

    相信很多人跟我一样,对Markdown是"一知半解",会打一点,知道一点,但是其实从没花哪怕一分钟了解过.其实除了标题粗体插入代码,Markdown还有很多有趣的基础语法和扩展语法 ...

  9. .NET 扩展方法(Extention Method)的要点

    扩展方法Extention Method的主要介绍在:http://msdn.microsoft.com/zh-cn/library/bb383977(v=vs.100).aspx. 扩展方法的意义在 ...

随机推荐

  1. Jersey构建restful风格的WebSerivices(二)

    一. 总体说明 XML和JSON 是最为常用的数据交换格式.本例子演示如何将java对象,转成XML输出. 二.流程 1.在上文的例子中,创建一个包“com.waylau.rest.bean” 2.在 ...

  2. C#全局键盘监听(Hook)

    一.为什么需要全局键盘监听? 在某些情况下应用程序需要实现快捷键执行特定功能,例如大家熟知的QQ截图功能Ctrl+Alt+A快捷键,只要QQ程序在运行(无论是拥有焦点还是处于后台运行状态),都可以按下 ...

  3. .NET Core MemoryCache缓存获取全部缓存键

    在Core中不能使用原HttpRuntime.Cache缓存,改为MemoryCache(Microsoft.Extensions.Caching.Memory). 现MemoryCache新版为2. ...

  4. web窗体ListView配置分页

    一.配置objectDataSource 1.选择业务逻辑层的类,再选择对应的分页方法 2.配置Select对应的方法,必须是一个带两个整型参数的方法,第一个参数表示要查看的第一条记录的前一条,第二个 ...

  5. C# 动态生成Html地图文件

    public void GPSModel(string x, string y, string ss)//动态地图文件 { if (x.Contains("-") &&am ...

  6. Day 62 Django第三天

    2.GET请求能够被cache,GET请求能够被保存在浏览器的浏览历史里面(密码等重要数据GET提交,别人查看历史记录,就可以直接看到这些私密数据)POST不进行缓存. 3.GET参数是带在URL后面 ...

  7. BZOJ4825: [Hnoi2017]单旋(Splay)

    题面 传送门 题解 调了好几个小时--指针太难写了-- 因为只单旋最值,我们以单旋\(\min\)为例,那么\(\min\)是没有左子树的,而它旋到根之后,它的深度变为\(1\),它的右子树里所有节点 ...

  8. 怎样使用Navicat Premium导出导入mysql数据库

    首先,在Navicat Premium中连接要导出数据库的mysql数据库. 2 1.填写好连接数据库的信息后就可以连接到需要导出的数据库了. 3 打开要导出的数据库. 4 将数据库的结构和数据导出为 ...

  9. Swift 里字符串(四)large sting

    对于普通的字符串,对应的_StringObject 有两个存储属性: _countAndFlagsBits: UInt64 _object: Builtin.BridgeObject _countAn ...

  10. Linux CentOS7系统探索

    这两天,突发奇想,想着用着微软家的windows系统很多年了,也想尝试一下其他的操作系统.很快的就想到了Linux操作系统,它不是面向用户的,而是面向服务器的,在服务器端的市场中占了很大的市场份额,备 ...