奇异递归模式,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