如有错误或不足之处,还望多多赐教,万分感谢。
扩展方法概念
MSDN 说:扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。这里的“添加”之所以使用引号,是因为并没有真正地向指定类型添加方法
扩展方法调用,很像实例方法,就像扩展了类的逻辑
1适用场景: 第三方的类,不适合修改源码,可以通过扩展方法增加逻辑
最怕扩展方法增加了,别的类又修改了,因为优先调用实例方法,。
2 适合组件式开发的扩展(.NetCore),定义接口或者类,是按照最小需求,但是在开发的时候又经常需要一些方法,就通过扩展方法 context.Response.WriteAsync 中间件的注册
3 扩展一些常见操作
会污染基础类型,一般少为object 没有约束的泛型去扩展
扩展方法的使用
如何定义扩展方法:
定义静态类,并添加public的静态方法,第一个参数 代表 扩展方法的扩展类。
它必须放在一个非嵌套、非泛型的静态类中(的静态方法);
它至少有一个参数;
第一个参数必须附加 this 关键字;
第一个参数不能有任何其他out/ref)
第一个参数不能是指针类型
当我们把扩展方法定义到其它程序集中时,一定要注意调用扩展方法的环境中需要包含扩展方法所在的命名空间!
如果要扩展的类中本来就有和扩展方法的名称一样的方法,到底会调用成员方法还是扩展方法呢?
编译器默认认为一个表达式是要使用一个实例方法,但如果没有找到,就会检查导入的命名空间和当前命名空间里所有的扩展方法,并匹配到适合的方法。例如:
//这里方法不在Student类里,是另外一个静态类中
//此处需要注意,this后面的类型可以理解为:需要添加扩展方法的类
public static void StudyPractise( this Student student)
{
Console.WriteLine("{0} {1}", student.Id, student.Name);
}
在实例方法调用时
Student student = new Student()
studen.StudyPractise();//此时我们却可以访问到StudyPractise方法。
扩展方法结合泛型和的使用
说到这里,我们正好可以回顾一下委托、泛型、匿名类以及lambda的使用
//例如需要对某个数据源进行筛选
List<Student> studentList = this.GetStudentList(); //常规情况下数据过滤 { //年纪小于30 var list = new List<Student>(); foreach (var item in studentList) { if (item.Age < 30) { list.Add(item); } } { //添加一个扩展方法,里面有两个参数(需要扩展的类,带返回值的委托)
//为什么在这里要使用到委托?逻辑解耦、提高代码重用性
//把重复的代码写在方法体力,把变化的部分通过委托进行传递
var result = studentList.ElevenWhere(s => s.Age < 30);
//如果需要使用泛型,调用ElevenWhereNew方法
//var result = studentList.ElevenWhereNew<Student>(s => s.Age < 30);
//此处<Student>其实可以省略不写,原因,调用方法之前已经确定是studentList,所以方法也是 foreach (var item in result) { Console.WriteLine(item.Name); } } }
静态类中的方法
/// <summary> /// 扩展方法:静态类里面的静态方法,第一个参数类型前面加上this /// </summary> public static class ExtendMethod { /// <summary> /// 一个方法,完成重复的步骤, /// 但是判断条件不同? 不同的通过委托传递 /// 1 完成对一组学生的过滤,把重复的代码写在这里,把变化的部分通过委托传递 /// 2 泛型完成对不同类型的数据过滤 /// </summary> /// <param name="resource"></param> /// <returns></returns> public static List<Student> ElevenWhere(this List<Student> resource, Func<Student, bool> func) { var list = new List<Student>(); foreach (var item in resource) { Console.WriteLine("进入数据检测"); Thread.Sleep(100); if (func.Invoke(item)) { list.Add(item); } } return list; }
//此时以上方法只是针对Student类型进行处理,可是如果我们想对任何类型的数据源都能做筛选呢?
//那么我们可以用泛型来实现
public static List<T> ElevenWhereNew(this List<T> resource, Func<T, bool> func)
{
var list = new List<T>();
foreach (var item in resource)
{
Console.WriteLine("进入数据检测");
Thread.Sleep(100);
if (func.Invoke(item))
{
list.Add(item);
}
}
}