简体   繁体   English

从基类方法返回派生类型

[英]Return derived type from base class method

I have a class hierarchy that looks similar to this: 我有一个类似于这个的类层次结构:

public class Base
{
    private List<string> attributes = new List<string>();

    public T WithAttributes<T>(params string[] attributes)
        where T : Base
    {
        this.attributes.AddRange(attributes);
        return this as T;
    }
}

public class Derived : Base
{
}

I want to call Base.WithAttributes from derived classes in a fluent-api style syntax and return the derived instance like shown in the example below. 我想以fluent-api样式语法从派生类调用Base.WithAttributes并返回派生实例,如下例所示。

void Main()
{
    Derived d = new Derived();

    // CS0411 The type arguments for method 'UserQuery.Base.WithAttributes<T>(params string[])' cannot be inferred from the usage.
    d.WithAttributes("one", "two"); 

    // Works, but type arguments must be explicity specified. 
    d.WithAttributes<Derived>("one", "two");

    // Works without explicitly specifying, but no access to private members!
    d.WithAttributesEx("one", "two");
}

public static class Extensions
{
    public static T WithAttributesEx<T>(this T obj, params string[] attributes)
        where T : Base
    {
        // No access to private members, argh!
        // obj.attributes.AddRange(attributes);
        return obj as T;
    }
}
  1. Why can't the compiler infer type arguments in the first example? 为什么编译器不能在第一个例子中推断出类型参数?
  2. Why does it work when called using an extension method? 使用扩展方法调用时为什么会起作用?
  3. Is there any way to make it work as an instance method on the base class without explicitly specifying type argument? 有没有办法让它作为基类的实例方法工作而不显式指定类型参数?

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

Why can't the compiler infer type arguments in the first example? 为什么编译器不能在第一个例子中推断出类型参数?

Type inference uses method arguments to infer type arguments. 类型推断使用方法参数来推断类型参数。 In the first example there are no method arguments which can be used to infer type argument. 在第一个示例中,没有可用于推断类型参数的方法参数。

Why does it work when called using an extension method? 使用扩展方法调用时为什么会起作用?

Extension method is actually a static method and object which you are 'extending' is passed as an argument to extension method call: Extension方法实际上是一个静态方法,你正在“扩展”的对象作为参数传递给扩展方法调用:

Extensions.WithAttributesEx<T>(d, "one", "two")

As stated above, type inference uses method arguments to find type arguments. 如上所述,类型推断使用方法参数来查找类型参数。 Here type argument can be inferred from the type of first method argument, which is Derived . 这里类型参数可以从第一个方法参数的类型推断出来,它是Derived

Is there any way to make it work as an instance method on the base class without explicitly specifying type argument? 有没有办法让它作为基类的实例方法工作而不显式指定类型参数?

Make base class generic and parametrize it with derived class (that is called Curiously Recurring Template Pattern ): 使基类通用并使用派生类(称为奇怪的重复模板模式 )对其进行参数化:

public class Base<T>
    where T : Base<T>
{
    private List<string> attributes = new List<string>();

    public T WithAttributes(params string[] attributes)            
    {
        this.attributes.AddRange(attributes);
        return this as T;
    }
}

public class Derived : Base<Derived>
{
}

Usage: 用法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM