寻找有关方差问题的解释
Looking for explanation about a variance issue
...毕竟这实际上可能不是方差问题。当我编译我的代码时,Visual Studio 会给我以下错误:
Type of conditional expression cannot be determined because there is no implicit conversion between 'ClassA' and 'ClassB'
我在这里阅读了这个错误,听起来确实不可能使用抽象 classes 作为接口之类的契约,我可以在其中使用派生的 classes 代替它们基地 class。为了让事情更简单,我写了一些测试 classes 来模拟我的实际代码的关系。请考虑以下事项:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AbstractClassImplicitConversion {
class Program {
static void Main(string[] args) {
StartClass temp = new StartClass();
}
}
public class StartClass
{
public AbstractClass _ac { get; private set; }
public StartClass()
{
bool which = true;
// this block will compile
/*
if( which)
_ac = new DerivedClass1();
else
_ac = new DerivedClass2();
*/
// this block will not compile
_ac = which ? new DerivedClass1() : new DerivedClass2();
}
}
public interface SomeInterface
{
void SiFoo();
}
public abstract class InnerAbstractClass
{
public abstract void IacFoo();
}
public abstract class AbstractClass : InnerAbstractClass, SomeInterface
{
public override void IacFoo() {
}
public void SiFoo() {
}
public abstract void OverrideMe();
public abstract void OverrideMeToo<T>();
}
public class DerivedClass1 : AbstractClass
{
public override void OverrideMe() {}
public override void OverrideMeToo<T>() {}
}
public class DerivedClass2 : AbstractClass
{
private int _blah;
public override void OverrideMe() {}
public override void OverrideMeToo<T>() {}
}
}
问题出在以下行:
_ac = which ? new DerivedClass1() : new DerivedClass2();
如果我使用内联 if,我将遇到可怕的编译器错误。但是,如果我改用这个:
if( which)
_ac = new DerivedClass1();
else
_ac = new DerivedClass2();
我的代码编译正常。
谁能解释一下这是什么原因造成的?我一直认为两者是等价的。谢谢!
语言标准就是这么定义的:
Either the type of first_expression and second_expression must be the same, or an implicit conversion must exist from one type to the other.
DerivedClass1
和 DerivedClass2
之间没有隐式转换 - 它仅通过存在的基础 class。运算符的规范并未说明它会查看赋值的结果值类型,因此编译器正在执行其设计目的。
我认为您需要按如下方式更改代码才能获得您想要的效果:
_ac = which ? (new DerivedClass1() as AbstractClass) : (new DerivedClass2() as AbstractClass);
希望对您有所帮助!
...毕竟这实际上可能不是方差问题。当我编译我的代码时,Visual Studio 会给我以下错误:
Type of conditional expression cannot be determined because there is no implicit conversion between 'ClassA' and 'ClassB'
我在这里阅读了这个错误,听起来确实不可能使用抽象 classes 作为接口之类的契约,我可以在其中使用派生的 classes 代替它们基地 class。为了让事情更简单,我写了一些测试 classes 来模拟我的实际代码的关系。请考虑以下事项:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AbstractClassImplicitConversion {
class Program {
static void Main(string[] args) {
StartClass temp = new StartClass();
}
}
public class StartClass
{
public AbstractClass _ac { get; private set; }
public StartClass()
{
bool which = true;
// this block will compile
/*
if( which)
_ac = new DerivedClass1();
else
_ac = new DerivedClass2();
*/
// this block will not compile
_ac = which ? new DerivedClass1() : new DerivedClass2();
}
}
public interface SomeInterface
{
void SiFoo();
}
public abstract class InnerAbstractClass
{
public abstract void IacFoo();
}
public abstract class AbstractClass : InnerAbstractClass, SomeInterface
{
public override void IacFoo() {
}
public void SiFoo() {
}
public abstract void OverrideMe();
public abstract void OverrideMeToo<T>();
}
public class DerivedClass1 : AbstractClass
{
public override void OverrideMe() {}
public override void OverrideMeToo<T>() {}
}
public class DerivedClass2 : AbstractClass
{
private int _blah;
public override void OverrideMe() {}
public override void OverrideMeToo<T>() {}
}
}
问题出在以下行:
_ac = which ? new DerivedClass1() : new DerivedClass2();
如果我使用内联 if,我将遇到可怕的编译器错误。但是,如果我改用这个:
if( which)
_ac = new DerivedClass1();
else
_ac = new DerivedClass2();
我的代码编译正常。
谁能解释一下这是什么原因造成的?我一直认为两者是等价的。谢谢!
语言标准就是这么定义的:
Either the type of first_expression and second_expression must be the same, or an implicit conversion must exist from one type to the other.
DerivedClass1
和 DerivedClass2
之间没有隐式转换 - 它仅通过存在的基础 class。运算符的规范并未说明它会查看赋值的结果值类型,因此编译器正在执行其设计目的。
我认为您需要按如下方式更改代码才能获得您想要的效果:
_ac = which ? (new DerivedClass1() as AbstractClass) : (new DerivedClass2() as AbstractClass);
希望对您有所帮助!