C#中的扩展方法

   扩展方法能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。
  扩展方法是在一个静态类中定义的,并且扩展方法也要是静态方法,并且扩展方法的第一个参数为要扩展的类型,必须附加一个this关键字。
  定义和调用扩展方法:
  1.定义一个静态类以包含扩展方法。
  2.该类必须对客户端代码可见。
  3.将该扩展方法实现为静态方法,并使其至少具有与包含类相同的可见性。
  4.该方法的第一个参数指定方法所操作的类型;该参数必须以 this 修饰符开头。
  5.在调用代码中,添加一条 using 指令以指定包含扩展方法类的命名空间。
  6.按照与调用类型上的实例方法一样的方式调用扩展方法。
例如,因ObservableCollection<T>与List<T>不能直接转换,则可以对继承IEnumerable接口的集合类进行扩展:

 public static class ArrayExtension
    {
        public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> array)
        {
            try
            {
                ObservableCollection<T> list = new ObservableCollection<T>();
                if (array == null) return list;
                foreach (var data in array)
                {
                    list.Add(data);
                }
                return list;
            }
            catch (Exception exp)
            {
                Logger.Log("ArrayExtension.ToObservableCollection:", exp);
                return new ObservableCollection<T>();
            }
        }
    }     

  C#编译器会自动检测当前在作用域中的所有static类,找出为一个给定的类型定义的扩展方法。如果自己写的扩展方法的命名空间不在当前命名空间中, 只要自己添加相对应的命名空间就可以了。 这时再调用List<T>类型对象时,就会多出一个.ToObservableCollection()方法。
  如果扩展方法包含参数,就可以在要扩展的类型(即第一个参数)以后顺序的添加扩展方法对应的参数既可,在调用的时候填写相应参数,不过第一个参数为要扩展的类型,在填写实参的时候并没有这个参数。
  在代码中,可以使用实例方法语法调用该扩展方法。 但是,编译器生成的中间语言 (IL) 会将代码转换为对静态方法的调用。 因此,并未真正违反封装原则。 实际上,扩展方法无法访问它们所扩展的类型中的私有变量。
注意:
  第一个参数不是由调用代码指定的,因为它表示正应用运算符的类型,并且编译器已经知道对象的类型。
  可以使用扩展方法来扩展类或接口,但不能重写扩展方法。 与接口或类方法具有相同名称和签名的扩展方法永远不会被调用。
  扩展方法被在命名空间级别放入范围中。

原文地址:https://www.cnblogs.com/infly123/p/3785939.html