从基类方法返回派生类型 [英] Return derived type from base class method

查看:92
本文介绍了从基类方法返回派生类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  public class Base 
{
私人列表< string> attributes = new List< string>();

public T WithAttributes< T>(params string [] attributes)
其中T:Base
{
this.attributes.AddRange(attributes);
将此返回为T;



public class Derived:Base
{
}

我想以流利的api风格语法从派生类中调用 Base.WithAttributes ,并返回派生类,如下面的例子。

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

// CS0411方法'UserQuery.Base.WithAttributes< T>(params string [])'的类型参数不能从用法中推断出来。
d.WithAttributes(one,two);

//工作,但类型参数必须明确指定。
d.WithAttributes< Derived>(one,two);

//无需明确指定,但无法访问私有成员!
d.WithAttributesEx(one,two);


public static class扩展
{
public static T WithAttributesEx< T>(this T obj,params string [] attributes)
where T :Base
{
//无法访问私人成员,argh!
// obj.attributes.AddRange(attributes);
将obj返回为T;





  1. 为什么不能编译器推断第一个示例中的类型参数?

  2. 为什么在使用扩展方法调用时工作?

  3. 是否有任何方法可以实现在基类中作为实例方法工作而不明确指定类型参数?

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

解决方案

< blockquote>

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


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


为什么在使用扩展方法调用时会起作用扩展方法实际上是一个静态方法,并且你'扩展'的对象作为参数传递给扩展方法call: / p>

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

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


有没有什么方法可以使它在基类
类中作为实例方法工作,而无需明确指定类型参数?

使基类具有泛型并用派生类对其进行参数化(称为好奇地重复发生模板模式):

  public class Base< T> 
其中T:Base< T>
{
私人列表< string> attributes = new List< string>();

public T WithAttributes(params string [] attributes)
{
this.attributes.AddRange(attributes);
将此返回为T;
}
}

public class Derived:Base< Derived>
{
}

用法:
$ bA pre $ Derived d = new Derived()。WithAttributes(one,two)。WithAttributes(three);


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.

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

解决方案

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:

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.

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");

这篇关于从基类方法返回派生类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆