C#扩展方法的理解

       “扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。

        这是msdn上说的,也就是你可以对String,Int,DataRow,DataTable等这些类型的基础上增加一个或多个方法,使用时不需要去修改或编译类型本身的代码。

先来看看在经常使用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);
        }
    }
这只是一个简单的例子,你可以做你自己的扩展方法。

msdn是这样规定扩展方法的:“扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。 它们的第一个参数指定该方法作用于哪个

类型,并且该参数以 this 修饰符为前缀。”通俗的说就是,扩展方法跟静态类的名称无关,只需要在一个静态类里面定义一个静态方法,第一个参数必须this T开头,

这个T就是一个泛型类型了。

小结:

本质上来说: 扩展方法是破坏原来的层次结构,通过网络结构加快业务逻辑处理

扩展方法不改变被扩展类的代码,不用重新编译、修改、派生被扩展类

扩展方法不能访问被扩展类的私有成员

扩展方法会被被扩展类的同名方法覆盖,所以实现扩展方法我们需要承担随时被覆盖的风险

扩展方法看似实现了面向对象中扩展对修改说不的特性,但是也违背了面向对象的继承原则,被扩展类的派生类是不能继承扩展扩展方法的,从而又违背了面向对象的多态性。

在我们稳定的引用同一个版本的类库,但是我们没有该类库的源代码,那么我们可以使用扩展方法;但是从项目的可扩展、可维护和版本控制方面来说,都不建议使用扩展方法进行类的扩展。



  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值