从基类方法返回派生类型

我有一个类似于这个的类层次结构:

public class Base { private List attributes = new List(); public T WithAttributes(params string[] attributes) where T : Base { this.attributes.AddRange(attributes); return this as T; } } public class Derived : Base { } 

我想以fluent-api样式语法从派生类调用Base.WithAttributes并返回派生实例,如下例所示。

 void Main() { Derived d = new Derived(); // CS0411 The type arguments for method 'UserQuery.Base.WithAttributes(params string[])' cannot be inferred from the usage. d.WithAttributes("one", "two"); // Works, but type arguments must be explicity specified. d.WithAttributes("one", "two"); // Works without explicitly specifying, but no access to private members! d.WithAttributesEx("one", "two"); } public static class Extensions { public static T WithAttributesEx(this T obj, params string[] attributes) where T : Base { // No access to private members, argh! // obj.attributes.AddRange(attributes); return obj as T; } } 
  1. 为什么编译器不能在第一个例子中推断出类型参数?
  2. 使用扩展方法调用时为什么会起作用?
  3. 有没有办法让它作为基类的实例方法工作而不显式指定类型参数?

相关: https : //stackoverflow.com/a/32123354/259808

为什么编译器不能在第一个例子中推断出类型参数?

类型推断使用方法参数来推断类型参数。 在第一个示例中,没有可用于推断类型参数的方法参数。

使用扩展方法调用时为什么会起作用?

Extension方法实际上是一个静态方法,你正在“扩展”的对象作为参数传递给扩展方法调用:

 Extensions.WithAttributesEx(d, "one", "two") 

如上所述,类型推断使用方法参数来查找类型参数。 这里类型参数可以从第一个方法参数的类型推断出来,它是Derived

有没有办法让它作为基类的实例方法工作而不显式指定类型参数?

使基类通用并使用派生类(称为奇怪的重复模板模式 )对其进行参数化:

 public class Base where T : Base { private List attributes = new List(); public T WithAttributes(params string[] attributes) { this.attributes.AddRange(attributes); return this as T; } } public class Derived : Base { } 

用法:

 Derived d = new Derived().WithAttributes("one", "two").WithAttributes("three");