C#语法之扩展
扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。这是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#语法之扩展的更多相关文章
- Swift2.1 语法指南——扩展
原档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programmi ...
- C#语法糖: 扩展方法(常用)
今天继续分享C#4.0语法糖的扩展方法,这个方法也是我本人比较喜欢的方法.大家先想想比如我们以前写的原始类型不能满足现在的需求,而需要在该类型中添加新的方法来实现时大家会怎么做.我先说一下我没有学习到 ...
- 学习php语法--数据库扩展(总结篇)
前 言 php php中的数据库扩展mysql语法--本篇学习都是通过使用数字天堂的HBuider开发环境,连接mysql数据.介绍php连接mysql数据库的代码与函数. 本篇学习主要有两 ...
- Objective-C语法之扩展(Extension)的使用
Objective-C 2.0增加了Class Extension用于解决两个问题: 可声明私有可读写的属性,而在类的声明中是同名的公开只读属性,从而来支持公开只读.私有可读写的属性 可声明私有方法: ...
- ExtJs4 笔记(2) ExtJs对js基本语法扩展支持
本篇主要介绍一下ExtJs对JS基本语法的扩展支持,包括动态加载.类的封装等. 一.动态引用加载 ExtJs有庞大的类型库,很多类可能在当前的页面根本不会用到,我们可以引入动态加载的概念来即用即取.这 ...
- ExtJs对js基本语法扩展支持
ExtJs对js基本语法扩展支持 本篇主要介绍一下ExtJs对JS基本语法的扩展支持,包括动态加载.类的封装等. 一.动态引用加载 ExtJs有庞大的类型库,很多类可能在当前的页面根本不会用到,我们可 ...
- [转载]ExtJs4 笔记(2) ExtJs对js基本语法扩展支持
作者:李盼(Lipan)出处:[Lipan] (http://www.cnblogs.com/lipan/) 本篇主要介绍一下ExtJs对JS基本语法的扩展支持,包括动态加载.类的封装等. 一.动态引 ...
- 一些Markdown扩展语法
相信很多人跟我一样,对Markdown是"一知半解",会打一点,知道一点,但是其实从没花哪怕一分钟了解过.其实除了标题粗体插入代码,Markdown还有很多有趣的基础语法和扩展语法 ...
- .NET 扩展方法(Extention Method)的要点
扩展方法Extention Method的主要介绍在:http://msdn.microsoft.com/zh-cn/library/bb383977(v=vs.100).aspx. 扩展方法的意义在 ...
随机推荐
- DBCC--CHECKIDENT
检查活或重置自增键的标识值,可以使用NORESEED 来检查当前标识值和标识列在表中的最大值. 如果当前标识值与表中数据冲突或希望将标识值重置到一个较小的值时,可以只用RESEED 来设置 DBCC ...
- .net core signalR 忽略https 证书
var connection = new HubConnectionBuilder().WithUrl(serverUrl, option => { option.HttpMessageHand ...
- NetCore入门篇:(三)Net Core项目Nuget及Bower包管理
一.创建项目 1.如何创建项目,参照上一篇文章 二.程序包介绍 1.Net Core的程序包分前后端两种,后端用nuget,前端用bower. 2.与Net 不同,Net Core引用nuget包时, ...
- 在MUI框架中使用video.js插件,并在暂停的时候利用Asp.net将观看时长保存到sqlserver数据库
本次保存数据的情况有三种: 在视频播放的时候点击暂停,将本视频的进度保存到数据库 利用mui内部的控件,返回上一页操作时,进行保存 安卓手机触发返回键的时候,进行保存 示例一: 在video标签上面添 ...
- UWP开发---嵌套DataTemplate&模板选择器
对于Json结构体items不完全一致的情况下,在UWP平台是如何处理数据,并通过不同的模板选择,进行显示呢? 一,嵌套Json分析 1,结构 通过抓取index的API(点击请求API)获取到的js ...
- Socket编程入门
socket基本知识 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. 建立网络通信连接至少要一对端口号(socket).socket本质是编程接口(AP ...
- java 处理json格式数据中的转义斜杠
1.{\"Count\":\"3\",\"ErrorString\":\"\",\"Success\" ...
- 902. Numbers At Most N Given Digit Set
We have a sorted set of digits D, a non-empty subset of {'1','2','3','4','5','6','7','8','9'}. (Not ...
- Python 读取大文件的方式
对于读取容量小的文件,可以使用下面的方法: with open("path", "r") as f: f.read() 但是如果文件容量很大,高达几个G或者十几 ...
- django 自定义中间件 middleware
Django 中间件 Django中的中间件是一个轻量级.底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出.中间件的设计为开发者提供了一种无侵入式的开发方式,增强 ...