我试图创建类Bar的实例,但我收到错误:
"无法隐式转换类型
ConsoleApplication1.Bar
ConsoleApplication1.BaseFoo<ConsoleApplication1.baseOutput, ConsoleApplication1.baseInput>
&#34;
知道我错过了什么,或者我做错了什么?任何建议都会很好。
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
}
}
答案 0 :(得分:3)
我将举例说明您为何无法这样做。
想象一下,你的课程写得像这样:
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
,而SomethingElse
是BaseOutput
。 然而,该对象实际上是一个 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; }
缓解了上述问题
答案 1 :(得分:1)
Bar
为BaseFoo<ExtendOutput, ExtendInput>
,CreateInstance()
要求BaseFoo<baseOutput, baseInput>
返回,因此无法返回Bar
BaseFoo<ExtendOutput, ExtendInput>
}。
无论ExtendOutput
是否继承baseOutput
,当您继承泛型类时,继承为invariant。
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 interface IBaseFoo<out T1, out T2>
{
public void DoSmth();
}
public class Bar : IBaseFoo<ExtendOutput, ExtendInput>
{
public void DoSmth()
{
}
}
public class Test
{
public void Show()
{
}
private IBaseFoo<baseOutput, baseInput> CreateInstance()
{
return new Bar();
}
}