建议101:使用扩展方法,向现有类型“添加”方法
2016-09-09 14:09
274 查看
建议101:使用扩展方法,向现有类型“添加”方法
考虑如何让一个sealed类型具备新的行为。以往我们会创建一个包装器类,然后为其添加方法,而这看上去一点儿也不优雅。我们也许会考虑修改设计,直接修改sealed类型,然后为其发布一个新的版本,但这依赖于你拥有全部的源码。更多的时候,我们会采取针对第三方公司提供的API进行编程的方式。对于我们来说,FCL是一组第三方公司(微软)提供给我们的最好的API。
包装类的编码形式如下:
可以看到,Student类型只提供了一个GetSex方法,它返回了一个bool值的结果。我们需要的是要将一个bool值转换为一个字符串,StudentConverter就是为了满足需求而创建的一个包装器类。调用者的代码看起来就应该是这样的:
但是我们知道,可以有更优美的形式让调用者像调用Student类型的实例方法一样来调用GetSexString了。这种更好的方式就是扩展方法:
扩展方法除了让调用着可以像调用类型自身的方法一样去调用扩展方法外,它还有一些其他的主要优点:
可以扩展密封类型;
可以扩展第三方程序集中的类型;
扩展方法可以避免不必要的深度继承体系。
扩展方法还有一些必须遵循的要求:
扩展方法必须在静态类中,而且该类不能是一个嵌套类;
扩展方法必须是静态的;
扩展方法的第一个参数必须是要扩展的类型,而且必须加上this关键字;
不支持扩展属性、事件。
值得注意的一点是,扩展方法还能够扩展接口。这让接口看上去也是可以扩展的。扩展方法的这个特性被广泛应用于提供LINQ查询功能的Enumerable类和Queryable类中。以Enumerable为例,针对IEnumerable<T>接口提供了非常丰富的一种方法,如Select:
它相当于让继承自IEnumerable<T>接口的任何子类都拥有了Select方法,而这些Select方法在用者看来,就好像是IEnumerable<T>接口所声明的一样。
转自:《编写高质量代码改善C#程序的157个建议》陆敏技
考虑如何让一个sealed类型具备新的行为。以往我们会创建一个包装器类,然后为其添加方法,而这看上去一点儿也不优雅。我们也许会考虑修改设计,直接修改sealed类型,然后为其发布一个新的版本,但这依赖于你拥有全部的源码。更多的时候,我们会采取针对第三方公司提供的API进行编程的方式。对于我们来说,FCL是一组第三方公司(微软)提供给我们的最好的API。
包装类的编码形式如下:
class Program { static void Main(string[] args) { Student student = new Student(); Console.WriteLine(StudentConverter.GetSexString(student)); } } public static class StudentConverter { public static string GetSexString(Student student) { return student.GetSex() == true ? "男" : "女"; } }
public class Student { public bool GetSex() { return false; } }
可以看到,Student类型只提供了一个GetSex方法,它返回了一个bool值的结果。我们需要的是要将一个bool值转换为一个字符串,StudentConverter就是为了满足需求而创建的一个包装器类。调用者的代码看起来就应该是这样的:
Console.WriteLine(StudentConverter.GetSexString(student));
但是我们知道,可以有更优美的形式让调用者像调用Student类型的实例方法一样来调用GetSexString了。这种更好的方式就是扩展方法:
class Program { static void Main(string[] args) { Student student = new Student(); Console.WriteLine(student.GetSexString()); } } public static class StudentExtension { public static string GetSexString(this Student student) { return student.GetSex() == true ? "男D" : "女?"; } }
扩展方法除了让调用着可以像调用类型自身的方法一样去调用扩展方法外,它还有一些其他的主要优点:
可以扩展密封类型;
可以扩展第三方程序集中的类型;
扩展方法可以避免不必要的深度继承体系。
扩展方法还有一些必须遵循的要求:
扩展方法必须在静态类中,而且该类不能是一个嵌套类;
扩展方法必须是静态的;
扩展方法的第一个参数必须是要扩展的类型,而且必须加上this关键字;
不支持扩展属性、事件。
值得注意的一点是,扩展方法还能够扩展接口。这让接口看上去也是可以扩展的。扩展方法的这个特性被广泛应用于提供LINQ查询功能的Enumerable类和Queryable类中。以Enumerable为例,针对IEnumerable<T>接口提供了非常丰富的一种方法,如Select:
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) { //具体代码省略 }
它相当于让继承自IEnumerable<T>接口的任何子类都拥有了Select方法,而这些Select方法在用者看来,就好像是IEnumerable<T>接口所声明的一样。
转自:《编写高质量代码改善C#程序的157个建议》陆敏技
相关文章推荐
- 编写高质量代码改善C#程序的157个建议——建议101:使用扩展方法,向现有类型“添加”方法
- 使用扩展方法,向现有类型“添加”方法
- 【怎样写代码】向现有类型“添加”方法 -- 扩展方法(二):扩展方法的实现与调用
- 【怎样写代码】向现有类型“添加”方法 -- 扩展方法(三):为枚举类型创建方法
- C#3.0扩展方法是给现有类型添加一个方法
- 【怎样写代码】向现有类型“添加”方法 -- 扩展方法(一):扩展方法概述
- 【怎样写代码】向现有类型“添加”方法 -- 扩展方法(四):在编译时绑定扩展方法的规则
- macOS 中使用 phpize 动态添加 PHP 扩展的错误解决方法
- C# 3.0 添加扩展方法扩展现有类
- 使用 Iisext.vbs 添加Web服务扩展文件的方法
- 复习扩展方法 涉及委托,这里我使用自定义委托类型 public delegate bb MyFunc<in T,out bb> (T arg)
- 使用libzip读取修改zip文件comment的方法(支持添加扩展字符)
- 为类库添加扩展方法的使用实例
- 使用扩展方法(this 扩展类型)
- 101,使用Category给API里面的类添加新方法
- 使用扩展方法和接口给对象添加“重置状态”功能
- 使用分类向某个现有类添加方法(类扩展,范畴)
- 使用扩展方法添加到String类中简化脚本注入处理
- HtmlHelper 添加扩展方法. 使用Lambda表达式作为参数
- 使用mvc时,在视图view中使用强类型视图,在web.config文件中添加命名空间namespace的引用不起作用,解决方法