c#中的奇异递归模式
奇异递归模式,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