我正在尝试创建Bar类的实例,但收到错误:



知道我丢失了什么或做错了什么吗?任何建议都会很好。

public class baseOutput
{
    public string output;
}

public class baseInput
{
    public string input;
}

public class ExtendOutput : baseOutput
{
    public long id;
}

public class ExtendInput : baseInput
{
    public long id;
}

public class BaseFoo<baseOutput, baseInput>
{
    protected virtual void DoSmth()
    {

    }
}

public class Bar : BaseFoo<ExtendOutput, ExtendInput>
{
    protected override void DoSmth()
    {
        base.DoSmth();
    }
}

public class Test
{
    public void Show()
    {

    }

    private BaseFoo<baseOutput, baseInput> CreateInstance()
    {
        return new Bar(); // Error right here
    }
}

最佳答案

我将举例说明为什么您无法这样做。

想象一下,您的类是这样编写的:

public class BaseFoo<TOutput, TInput>
    where TOutput : BaseOutput
{
    public TOutput Something { get; set; }
}

public class Bar : BaseFoo<ExtendOutput, ExtendInput>
{

}

public class BaseInput { }
public class BaseOutput { }
public class ExtendOutput : BaseOutput { }
public class SomethingElse : BaseOutput { }

现在,您可以使用以下方法:
private BaseFoo<BaseOutput, BaseInput> CreateInstance()
{
    //At this point, Something will be of type ExtendOutput.
    return new Bar();
}

因此,我们这样称呼它:
var myBar = CreateInstance();

现在,mybar.Something的类型为BaseOutput。没关系,因为ExtendOutput : BaseOutput,对不对?不完全的。

当我们这样做时会发生什么:
myBar.Something = new SomethingElse();

这是正确的,因为Something需要BaseOutput,而SomethingElseBaseOutput。但是,该对象实际上是Bar,它明确表示应为ExtendOutput

如果我们尝试将其回退,问题将更加清楚:
var myBaseFoo = CreateInstance();
myBaseFoo.Something = new SomethingElse();
Bar myBar = (Bar)myBaseFoo;
myBar.Something; // Here, we're told it's going to be an `ExtendOutput`,
                 // but we get a `SomethingElse`?

这显然是错误的。这就是为什么您被阻止去做自己想做的事情的原因。您可以使用covariance来实现这种行为。

协方差使传递TOutput成为非法。所以,这条线
public TOutput Something { get; set; }

无效。我们只允许公开getter:
public TOutput Something { get; }

缓解了上述问题

关于C#创建从基类继承的泛型类的实例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37497098/

10-09 18:09