为什么使用父类型的父类型调用泛型扩展方法?

时间:2015-09-01 23:33:58

标签: c# generics extension-methods

请考虑以下代码:

public static class ParentHelper {
   public static string GetTypeString<T>(this T parent) where T : Parent {
      return typeof(T).ToString();
   }
}

public abstract class Parent {
   public string GetMyType(bool withReflection) {
      return withReflection
         ? typeof(ParentHelper)
            .GetMethod("GetTypeString")
            .MakeGenericMethod(GetType()).Invoke(null, new object[] { this }) as string
         : this.GetTypeString();
   }
}

public class Child : Parent {
}

void Main() {
   Child child = new Child();
   child.GetMyType(false).Dump();            // Parent
   ((Parent) child).GetMyType(false).Dump(); // Parent
   child.GetMyType(true).Dump();             // Child
   ((Parent) child).GetMyType(true).Dump();  // Child
}

令我惊讶的是,GetMyType方法会根据其调用GetTypeString的方式返回不同的值(请参阅Main方法中的注释)。

使用普通的GetTypeString语法时,object.ExtensionMethod()扩展方法是否有办法处理类类型而不是父类?

请注意,这段代码是我可以放在一起的最小例子 - 我的用法完全不同(不返回类型,而是一个装饰子类的属性)。

2 个答案:

答案 0 :(得分:3)

是的,您需要将typeof(T)替换为parent.GetType(),而不是。{/ p>

他们做不同的事情。

答案 1 :(得分:2)

this.GetTypeString();已编译为ParentHelper.GetTypeString<Parent>(),因为它是从Parent.GetMyType传递的类型。

通常的解决方案 - 让Parent通用其子代(也就是奇怪的递归模板),如:

 public abstract class Parent<TChild> where TChild : Parent<TChild>
 {
     public string GetMyType()
     { 
         return ((TChild)this).GetTypeString();
     }
 }

或者你可以使用类似于构造反射调用的GetType(),但它会放弃一些编译类型的安全性。