奇異遞歸模式,Curiously Recurring Template Pattern (CRTP) ,作用是能使父類中能夠使用子類的信息。下面是我對這個問題的分析過程。
按照一般的繼承關系,父類是無法訪問到子類的,所以很自然的想到了c#中的泛型,將子類作為父類的泛型版本中的<T>,就能通過父類中的<T>來訪問子類信息。
class App {static void Main(){foreach (var str in DerivedA.NowClsMemberInfo){Console.WriteLine(str);}Console.ReadLine();} }public class BaseA<T> {public static IEnumerable<string> NowClsMemberInfo{get{foreach (var memberInfo in typeof (T).GetMembers()){yield return memberInfo.Name;}}} }public class DerivedA : BaseA<DerivedA> {public string StrA { get; set; } }
DerivedA : BaseA<DerivedA>看著有些別扭,T1:BaseA<T2>中的T2,又要滿足T2:BaseA<T3>,有點遞歸的意思。
這里的T,我們是當作子類來用的,所以必須加一個約束,繼承自父類,即:
public class BaseA<T> where T : BaseA<T> {public static IEnumerable<string> NowClsMemberInfo{get{foreach (var memberInfo in typeof (T).GetMembers()){yield return memberInfo.Name;}}} }
這是為了避免被人以比如BaseA<string>的形式調用,如果父類中的T(子類)用到了父類中的成員,類似于BaseA<string>的類就會出現編譯錯誤,如:
public class BaseA<T> {public static IEnumerable<string> NowClsMemberInfo{get{foreach (var memberInfo in typeof (T).GetMembers()){yield return memberInfo.Name;}}}public T InstanceNow { get; set; }public void DoSomething(){InstanceNow.DoSomething();} }
所以:
public class BaseA<T> where T : BaseA<T> {public static IEnumerable<string> NowClsMemberInfo{get{foreach (var memberInfo in typeof (T).GetMembers()){yield return memberInfo.Name;}}}public T InstanceNow { get; set; }public void DoSomething(){InstanceNow.DoSomething();} }
參照的資料:
http://zpbappi.com/curiously-recurring-template-pattern-in-csharp/
https://www.zhihu.com/question/27421302
?