(转)c# 扩展方法
扩展方法能够向现有类型“添加”方法,而无需创建新的派生类型,重新编译或以其他方式修改原始类型。扩展方法必须是静态方法,可以像实例方法一样进行调用。且调用同名中实际定义的方法优先级要高于扩展方法。
先来看看在经常使用List类型中使用扩展方法的例子,首先看看List是如何定义的:
// 摘要:
// Represents a strongly typed list of objects that can be accessed by index.
// Provides methods to search, sort, and manipulate lists.To browse the .NET
// Framework source code for this type, see the Reference Source.
//
// 类型参数:
// T:
// The type of elements in the list.
[Serializable]
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
public class List<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
{
// 摘要:
// Initializes a new instance of the System.Collections.Generic.List<T> class
// that is empty and has the default initial capacity.
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
public List();
//
// 摘要:
// Initializes a new instance of the System.Collections.Generic.List<T> class
// that contains elements copied from the specified collection and has sufficient
// capacity to accommodate the number of elements copied.
//
// 参数:
// collection:
// The collection whose elements are copied to the new list.
//
// 异常:
// System.ArgumentNullException:
// collection is null.
public List(IEnumerable<T> collection);
……
}
在List的类型定义中我们并没有看到有定义Union方法的地方,但是当我们在调用的时候就会出现:
<span style="white-space:pre"> </span>/// <summary>
/// 通过集合使用
/// </summary>
/// <param name="needSearchList"></param>
/// <param name="areaid"></param>
/// <returns></returns>
public List<AreaLineInfoModel> UseSetSearchCollection(List<AreaLineInfoModel> needSearchList, int areaid)
{
if (needSearchList == null || !needSearchList.Any()) return null;
const int area15 = 15;
var area15List = new List<AreaLineInfoModel>();
const int area16 = 16;
var area16List = new List<AreaLineInfoModel>();
const int area17 = 17;
var area17List = new List<AreaLineInfoModel>();
needSearchList.ForEach(
m =>
{
if (m.AreaIdList.Contains(area15)) area15List.Add(m);
if (m.AreaIdList.Contains(area16)) area16List.Add(m);
if (m.AreaIdList.Contains(area17)) area17List.Add(m);
});
if (areaid == area15) return area15List.Union(area16List).Union(area17List).ToList();
if (areaid == area16) return area16List.Union(area15List).Union(area17List).ToList();
if (areaid == area17) return area17List.Union(area15List).Union(area16List).ToList();
return null;
}
其中的Union方法哪里来的呢?我们转到定义看一看:
namespace System.Linq
{
public static class Enumerable
{
……
public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) {
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return UnionIterator<TSource>(first, second, null);
}
}
}
so,也就是说,List的一个实例里面可以调用Enumerable里面的Union方法,如果我们不知道有扩展方法这回事的时候,以通常的想法,通过继承关系来找Union方法,会发现,List并没有实现Union方法,而且在继承的接口中也没有定义Union方法。这就比较纳闷了,这不是违背了面向对象的三大基本原则么?此话后说,我们先来自己实现一个扩展方法:
public interface IFreshList<T>
{
}
public static class testjinni
{
public static IFreshList<TSource> Union<TSource>(this IFreshList<TSource> first, IFreshList<TSource> second)
{
return second;
}
}
public class MyList<T> : IFreshList<T>
{
}
public class use
{
public void meth()
{
var temiList=new MyList<int>();
var mdaidnnf = new MyList<int>();
temiList.Union(mdaidnnf);
}
}
这只是一个简单的例子,你可以做你自己的扩展方法。
所有对象都能使用扩展:
public static class ExtendExt
{
public static void FuncExt(this object obj)
{
int b = 0;
}
}
msdn是这样规定扩展方法的:“扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。 它们的第一个参数指定该方法作用于哪个
类型,并且该参数以 this 修饰符为前缀。”通俗的说就是,扩展方法跟静态类的名称无关,只需要在一个静态类里面定义一个静态方法,第一个参数必须this T开头,
这个T就是一个泛型类型了。
小结:
本质上来说: 扩展方法是破坏原来的层次结构,通过网络结构加快业务逻辑处理;
扩展方法不改变被扩展类的代码,不用重新编译、修改、派生被扩展类;
扩展方法不能访问被扩展类的私有成员;
扩展方法会被被扩展类的同名方法覆盖,所以实现扩展方法我们需要承担随时被覆盖的风险;
扩展方法看似实现了面向对象中扩展对修改说不的特性,但是也违背了面向对象的继承原则,被扩展类的派生类是不能继承扩展扩展方法的,从而又违背了面向对象的多态性。;
在我们稳定的引用同一个版本的类库,但是我们没有该类库的源代码,那么我们可以使用扩展方法;但是从项目的可扩展、可维护和版本控制方面来说,都不建议使用扩展方法进行类的扩展。
文章转载自:https://blog.csdn.net/qin_zhangyongheng/article/details/52469476
(转)c# 扩展方法的更多相关文章
- .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法
.NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法 0x00 为什么需要Map(MapWhen)扩展 如果业务逻辑比较简单的话,一条主管道就够了,确实用不到 ...
- .NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类
.NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类 0x00 为什么要引入扩展方法 有的中间件功能比较简单,有的则比较复杂,并且依赖其它组件.除 ...
- 为IEnumerable<T>添加RemoveAll<IEnumerable<T>>扩展方法--高性能篇
最近写代码,遇到一个问题,微软基于List<T>自带的方法是public bool Remove(T item);,可是有时候我们可能会用到诸如RemoveAll<IEnumerab ...
- C#的扩展方法解析
在使用面向对象的语言进行项目开发的过程中,较多的会使用到“继承”的特性,但是并非所有的场景都适合使用“继承”特性,在设计模式的一些基本原则中也有较多的提到. 继承的有关特性的使用所带来的问题:对象的继 ...
- 扩展方法(C#)
扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型.扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用. 下面的示例为String添加 ...
- 扩展方法解决LinqToSql Contains超过2100行报错问题
1.扩展方法 using System; using System.Collections.Generic; using System.Linq; using System.Web; using Sy ...
- C#扩展方法
扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法就相当于一个马甲,给一个现有类套上,就可以为这个类添加其他方法了. 马甲必须定义为stati ...
- 枚举扩展方法获取枚举Description
枚举扩展方法 /// <summary> /// 扩展方法,获得枚举的Description /// </summary> /// <param name="v ...
- 扩展方法 1 简单的string扩展方法
这里是关于 String的简单扩展方法 (静态类 静态方法 this 类型 这里是string) static class Program { static void Main(string[] ar ...
- C#中的扩展方法
扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用. 以上是msdn官网对扩展方 ...
随机推荐
- mint-ui之datetime-picker使用
一基本使用<template> <mt-datetime-picker ref="picker" type="time" v-model=&q ...
- bzoj 4445 小凸想跑步 - 半平面交
题目传送门 vjudge的快速通道 bzoj的快速通道 题目大意 问在一个凸多边形内找一个点,连接这个点和所有顶点,使得与0号顶点,1号顶点构成的三角形是最小的概率. 假设点的位置是$(x, y)$, ...
- tp框架中的一些疑点知识--cookie和session的配置
不同的浏览器采用不同的方式保存Cookie. IE浏览器会在"C:\Documents and Settings\你的用户名\Cookies"文件夹下以文本文件形式保存,一个文本文 ...
- 如何使用thinkphp的model来验证前端表单?
为了增加安全性, 在向model表中写入和修改数据时, 最好是调用 create方法来保证安全, 然后再调用add和save方法: if($Model->Validate($validate)- ...
- bzoj1497 [NOI2006]最大获利 最大权闭合子图
链接 https://www.lydsy.com/JudgeOnline/problem.php?id=1497 思路 最大权闭合子图的裸题 一开始知道是这个最大权闭合子图(虽然我不知道名字),但是我 ...
- CF767C 记录错误
链接 https://codeforces.com/contest/767/problem/C 思路 之所以把这个题放进来,是因为要记录错误 情况不止一种 所以答案存储就是>=2了 代码 #in ...
- Java8 函数式接口-Functional Interface
目录 函数式接口: JDK 8之前已有的函数式接口: 新定义的函数式接口: 函数式接口中可以额外定义多个Object的public方法一样抽象方法: 声明异常: 静态方法: 默认方法 泛型及继承关系 ...
- Flyway Overview and Installation
https://flywaydb.org/documentation/ Flyway is an open-source database migration tool. It strongly fa ...
- Codeforces 855C. Helga Hufflepuff's Cup----树形DP
z最近在学习树形DP...好难啊. 在cf上找到了一题c题当模版马克一下. 题目不贴了..>>http://codeforces.com/problemset/problem/855/C& ...
- ActiveReports 大数据分析报告:公交车司乘冲突引发的刑事案件
公交车司乘冲突刑事案件总体情况 公交车司乘冲突引发的刑事案件总量稳中有升 (注:本报告界定的“公交车司乘冲突刑事案件”,是指案件诱因为公交车司机与乘客在乘车过程中发生冲突而引发的刑事案件.包括但不限于 ...