【问题标题】:Looking for explanation about a variance issue [duplicate]寻找有关差异问题的解释[重复]
【发布时间】:2015-09-04 18:49:22
【问题描述】:

...毕竟,这实际上可能不是差异问题。当我编译我的代码时,Visual Studio 会给我以下错误:

无法确定条件表达式的类型,因为 'ClassA' 和 'ClassB' 之间没有隐式转换

我在这里读到了这个错误,听起来确实不可能将抽象类用作接口之类的契约,而我可以使用派生类代替它们的基类。为了使事情更简单,我编写了一些模拟实际代码关系的测试类。请考虑以下几点:

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

我的代码编译得很好。

谁能解释这是什么原因?我一直认为两者是等价的。谢谢!

【问题讨论】:

  • 你可以通过转换为基类来解决这个问题。
  • 虽然这是一个好看的问题,但我看不出它与您可能已经看过的有什么不同。版本“为什么两个兄弟派生类之间没有隐式转换”可能是一个很好的非重复替代方案,但我怀疑你已经知道答案了。还有其他答案,例如stackoverflow.com/a/202296/477420,可能会更好,但与 Daniel A. White 的好答案基本相同。
  • 附注:考虑更新您的帖子,标题为“三元/条件运算符” - 这样它可以成为未来搜索的好路标。

标签: c# covariance variance


【解决方案1】:

这正是语言标准的定义方式:

first_expression 和 second_expression 的类型必须相同,或者必须存在从一种类型到另一种类型的隐式转换。

DerivedClass1DerivedClass2 之间没有隐式转换 - 它仅通过存在的基类。运算符的规范并没有说它会查看赋值的结果值类型,因此编译器正在执行它的设计目标。

来源:https://msdn.microsoft.com/en-us/library/ty67wk28.aspx

【讨论】:

  • 感谢您的链接!
【解决方案2】:

我认为您需要将代码更改如下以获得您正在寻找的效果:

_ac = which ? (new DerivedClass1() as AbstractClass) : (new DerivedClass2() as AbstractClass);

希望这会有所帮助!

【讨论】:

  • as 在这里太过分了。请改用一元 (Type)
猜你喜欢
  • 1970-01-01
  • 2015-03-26
  • 2010-11-21
  • 1970-01-01
  • 1970-01-01
  • 2016-06-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-29
相关资源
最近更新 更多