C# 在三元/条件运算符中强制转换时出现奇怪的编译器错误

C# 在三元/条件运算符中强制转换时出现奇怪的编译器错误,c#,casting,operators,C#,Casting,Operators,我遇到以下代码的意外编译器错误: bool b = true; //or false StringBuilder builder = ...; // a string builder filled with content IVersePart vp = b ? (DualLanguageVersePart)builder : (VersePart)builder; DualLanguageVersePart和VersePart都实现了IVersePart接口。 DualLanguageVer

我遇到以下代码的意外编译器错误:

bool b = true; //or false
StringBuilder builder = ...; // a string builder filled with content
IVersePart vp = b ? (DualLanguageVersePart)builder : (VersePart)builder;
DualLanguageVersePart和VersePart都实现了IVersePart接口。 DualLanguageVersePart和VersePart都具有StringBuilder形式的显式强制转换运算符

由于这两个类都实现了vp类型的接口,我希望它能够完美地工作,或者至少能够正确编译。相反,编译器报告不能在这两种类型之间进行隐式转换


为什么不起作用?

我以前遇到过这个问题,三元运算符要求两种类型的真结果或假结果要么是同一类型,要么将它们强制转换为同一类型。

我以前遇到过这个问题,三元运算符要求两种类型的真结果或假结果要么是同一类型,或者将它们转换为相同的类型。

两个部分必须具有相同的类型,因此请尝试以下操作:

IVersePart vp = b ? 
  (IVersePart)(DualLanguageVersePart)builder :
  (IVersePart)(VersePart)builder;

<> > C编译器比C++编译器更容易理解:

两个部分必须具有相同的类型,所以请尝试:
IVersePart vp = b ? 
  (IVersePart)(DualLanguageVersePart)builder :
  (IVersePart)(VersePart)builder;

<> > C编译器比C++编译器更容易理解:

三元运算符需要返回一种类型,因为它只是一个语句。因此,当运算符的两个部分返回不同的类型时,编译器将尝试通过悄悄地将一个转换为另一个来允许这一操作。您没有从DualLanguageVersePart到VersePart的转换,反之亦然

一个简单的修复方法是只需在IVersePart中添加第二个cast:


三元运算符需要能够返回一种类型,因为它只是一条语句。因此,当运算符的两个部分返回不同的类型时,编译器将尝试通过悄悄地将一个转换为另一个来允许这一操作。您没有从DualLanguageVersePart到VersePart的转换,反之亦然

一个简单的修复方法是只需在IVersePart中添加第二个cast:


三值运算要求true和false返回相同的类型。这里有一种方法可以解决这个问题,虽然有点草率

IVersePart vp = b 
    ? (IVersePart)((DualLanguageVersePart)builder) 
    : (IVersePart)((VersePart)builder); 

三值运算要求true和false返回相同的类型。这里有一种方法可以解决这个问题,虽然有点草率

IVersePart vp = b 
    ? (IVersePart)((DualLanguageVersePart)builder) 
    : (IVersePart)((VersePart)builder); 

这是一个糟糕的设计。Cast操作符不应该这样使用

最好有一个ctor来处理这个问题,事实上,它试图构造一个新的对象

IVersePart vp = new DualLanguageVersePart(builder);
或者,您可以使用工厂:

IVersePart vp = VersePart.DualOrSingluar(builder, b);

这是一个糟糕的设计。Cast操作符不应该这样使用

最好有一个ctor来处理这个问题,事实上,它试图构造一个新的对象

IVersePart vp = new DualLanguageVersePart(builder);
或者,您可以使用工厂:

IVersePart vp = VersePart.DualOrSingluar(builder, b);

运算符隐式以外的任何运算符的结果类型都由操作数而不是上下文确定


与这里所说的大多数智慧相反,这两个论点不必是同一类型的。如果一种类型派生自另一种类型,则三元运算符结果将是基类型。但在您的示例中,有多种常见的基类型:至少是Object和IVersePart,而C语言不会让编译器尝试找出哪一种更好。

除运算符隐式外,任何运算符的结果类型都由操作数而不是上下文决定


与这里所说的大多数智慧相反,这两个论点不必是同一类型的。如果一种类型派生自另一种类型,则三元运算符结果将是基类型。但在您的示例中有多种常见的基类型:至少是Object和IVersePart,C语言不会让编译器尝试找出哪种更好。

您的可能重复描述了编译器错误,但没有提供确切的错误文本或出现错误的行号。这可能是很重要的信息,你认为?你描述的编译器错误可能是重复的,但没有提供准确的错误文本,或者错误发生的行号。这可能是重要的信息,你觉得吗?体面的C++编译器也不允许这样做。至少GCC不会。因为你可以不能,因为显式的C++操作符正在创建一个新的实例,要么是DualAugAgEngEvsEffice要么是VeleSePa。至少GCC不会。不,你不能,因为显式cast操作符正在创建DualLanguageVersePart或VersePart的新实例。但是在这些场景中总会有对象和一些常见的接口。如果一个操作数的类型T是另一个操作数类型s的子类型,那么s是编译时所有共享类型的超集,因此是最佳转换。在这种情况下,这意味着仅将一个操作数强制转换为IVersePart就足以解决歧义。尝试一下。但在这些场景中总会有对象和一些常见的接口。这和在两部歌剧中总是要求相同的类型有什么不同
nds?如果一个操作数的类型T是另一个操作数的类型s的子类型,则s是编译时所有共享类型的超集,因此是最佳转换。在这种情况下,这意味着仅将一个操作数强制转换为IVersePart就足以解决歧义。试试看,不是真的。一个操作数的类型成为另一个操作数的子类型就足够了。不正确。一个操作数的类型成为另一个操作数的子类型就足够了。