代码改变世界

【More Effective C#】扩展方法

2010-10-12 08:17  空逸云  阅读(600)  评论(1编辑  收藏  举报

  C#3.0中增加了许多新特性.其中.扩展方法允许我们在不修改原有代码的基础上扩展类/接口的功能.有技巧的运用该特性.能写出有效率/易维护/美观的代码.

增强现有接口

   C#2.0提供了许多泛型与容器的接口和类.最常见的如IComparable<T>常常需要新建一个Comparable来进行排序比较等等..但其默认只有一个CompareTo方法.在以前.我们只能手动添加.并且很难复用代码.如今.利用扩展方法.可以很方便地扩展该接口.

 


public static class Comparable
    {
        
public static bool LessThan<T>(this T left, T right) where T : IComparable<T>
        {
            
return left.CompareTo(right) < 0;
        }

        
public static bool GreaterThan<T>(this T left, T right) where T : IComparable<T>
        {
            
return left.CompareTo(right) > 0;
        }
        
public static bool LessThanEqual<T>(this T left, T right) where T : IComparable<T>
        {
            
return left.CompareTo(right) <= 0;
        }
        
public static bool GreaterThanEqual<T>(this T left, T right) where T : IComparable<T>
        {
            
return left.CompareTo(right) >= 0;
        }
    }

 

 如此一来.只要我们引用该类的命名空间.便可扩展的使用扩展方法.例如:

 


public class Student : IComparable<Student>
    {
        
public int CompareTo(Student other)
        {
            
return StuNo.CompareTo(other.StuNo);
        }

        
public int StuNo { getset; }
        
public string StuName { getset; }
    }

Student a = new Student() { StuNo = 1, StuName = "a" };
Student b = new Student() { StuNo = 2, StuName = "b" };
Console.WriteLine(a.LessThan(b));

 

 注意!若是某个类需要定义一个方法,而这个类所实现的接口中也给出了同名的扩展方法,那么也许会导致一些意料之外的行为.根据方法的解析规则,类中的方法将会被优先调用,不过这个解释发生在编译器.若是通过接口来调用方法,则调用方法上的扩展方法,而非类的方法.

 增强现有类型

   除了能扩展接口.同样.扩展方法对类也有强大的支持.C#3.0中提供了许多扩展方法.特别是对于泛型容器的支持特别丰富.有时候.我们可能也会根据需要增加自己的扩展方法.例如.有一个学生的容器.可能需要增加对于学生的特别查询.如最近旷课最多的学生.请假最多的学生等.以前.我们可以自己写一个学生的列表类StudentList继承List<Student>.但现在我们可以直接扩展List<Student>.前者相比较后者,存在着更多的限制.扩展方法是用IEnumerable<Student>作为参数,而派生类基于List<Student>,即强制要求使用一种特定的存储模型.因此.前者的做法无法与一系列的迭代方法组合使用.使方法的使用者受到不必要的约束.后者的使用更为灵活.

 扩展方法的建议

  虽然扩展方法给我们带来很大的便利.但这不总是设计上的首选.只有在重用项目扩展功能.最好不要在不同的命名空间中声明同名的扩展方法.这样会增加后期的维护成本.扩展方法尽量不要重载.更应该使用与功能更贴切的签名.