標籤:優先順序 his elements lex ring eset 靜態 capacity who
擴充方法能夠向現有類型“添加”方法,而無需建立新的衍生類別型,重新編譯或以其他方式修改原始類型。擴充方法必須是靜態方法,可以像執行個體方法一樣進行調用。且調用同名中實際定義的方法優先順序要高於擴充方法。
先來看看在經常使用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); } }
這隻是一個簡單的例子,你可以做你自己的擴充方法。
所有對象都能使用擴充:
public static class ExtendExt
{
public static void FuncExt(this object obj)
{
int b = 0;
}
}
msdn是這樣規定擴充方法的:“擴充方法被定義為靜態方法,但它們是通過執行個體方法文法進行調用的。 它們的第一個參數指定該方法作用於哪個
類型,並且該參數以 this 修飾符為首碼。”通俗的說就是,擴充方法跟靜態類的名稱無關,只需要在一個靜態類裡面定義一個靜態方法,第一個參數必須this T開頭,
這個T就是一個泛型型別了。
小結:
本質上來說: 擴充方法是破壞原來的階層,通過網路結構加快商務邏輯處理;
擴充方法不改變被擴充類的代碼,不用重新編譯、修改、派生被擴充類;
擴充方法不能訪問被擴充類的私人成員;
擴充方法會被被擴充類的同名方法覆蓋,所以實現擴充方法我們需要承擔隨時被覆蓋的風險;
擴充方法看似實現了物件導向中擴充對修改說不的特性,但是也違背了物件導向的繼承原則,被擴充類的衍生類別是不能繼承擴充擴充方法的,從而又違背了物件導向的多態性。;
在我們穩定的引用同一個版本的類庫,但是我們沒有該類庫的原始碼,那麼我們可以使用擴充方法;但是從項目的可擴充、可維護和版本控制方面來說,都不建議使用擴充方法進行類的擴充。
文章轉載自:52469476
(轉)c# 擴充方法