我刚刚遇到一个奇怪的错误:
private bool GetBoolValue()
{
//Do some logic and return true or false
}
Run Code Online (Sandbox Code Playgroud)
然后,在另一种方法中,这样的事情:
int? x = GetBoolValue() ? 10 : null;
Run Code Online (Sandbox Code Playgroud)
很简单,如果方法返回true,则为Nullable intx 赋值10 .否则,将null赋给nullable int.但是,编译器抱怨:
错误1无法确定条件表达式的类型,因为
int和之间没有隐式转换<null>.
我疯了吗?
我对这个小C#quirk感到有点难过:
给定变量:
Boolean aBoolValue;
Byte aByteValue;
Run Code Online (Sandbox Code Playgroud)
以下编译:
if (aBoolValue)
aByteValue = 1;
else
aByteValue = 0;
Run Code Online (Sandbox Code Playgroud)
但这不会:
aByteValue = aBoolValue ? 1 : 0;
Run Code Online (Sandbox Code Playgroud)
错误说:"不能隐式地将类型'int'转换为'byte'."
当然,这个怪物会编译:
aByteValue = aBoolValue ? (byte)1 : (byte)0;
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?
编辑:
使用VS2008,C#3.5
可能重复:
条件运算符无法隐式转换?
为什么null需要显式类型转换?
我有一个搜索,并没有找到一个很好的解释为什么发生以下情况.
我有两个具有共同接口的类,我尝试使用三元运算符初始化此接口类型的实例,如下所示但是无法编译错误"无法确定条件表达式的类型,因为之间没有隐式转换'xxx.Class1'和'xxx.Class2':
public ConsoleLogger : ILogger { .... }
public SuppressLogger : ILogger { .... }
static void Main(string[] args)
{
.....
// The following creates the compile error
ILogger logger = suppressLogging ? new SuppressLogger() : new ConsoleLogger();
}
Run Code Online (Sandbox Code Playgroud)
如果我明确地将第一个conditioin强制转换为我的界面,这是有效的:
ILogger logger = suppressLogging ? ((ILogger)new SuppressLogger()) : new ConsoleLogger();
Run Code Online (Sandbox Code Playgroud)
显然我总能做到这一点:
ILogger logger;
if (suppressLogging)
{
logger = new SuppressLogger();
}
else
{
logger = new ConsoleLogger();
}
Run Code Online (Sandbox Code Playgroud)
替代方案很好,但我不能完全理解为什么第一个选项因隐式转换错误而失败,因为在我看来,这两个类都是ILogger类型,我不是真的想要进行转换(隐式或显式) ).我敢肯定这可能是一个静态语言编译问题,但我想了解发生了什么.
我刚刚遇到这个(编写代码来演示"问题"):
public ICollection<string> CreateCollection(int x)
{
ICollection<string> collection = x == 0
? new List<string>()
: new LinkedList<string>();
return collection;
}
Run Code Online (Sandbox Code Playgroud)
编译器抱怨:
Fehler CS0173:Der Typ des bedingten Ausdrucks kann nicht bestimmt werden,weil keine implizite Konvertierung zwischen"System.Collections.Generic.List"und"System.Collections.Generic.LinkedList"erfolgt.
其翻译大致为:
无法确定条件运算符的类型,因为List和LinkedList之间没有隐式转换.
我可以看到为什么编译器抱怨,但是,嘿,来吧.它试图发挥愚蠢.我可以看到两个表达式不是同一类型,而是有一个共同的祖先,作为奖励,左侧的类型也是共同的祖先.我相信编译器也可以看到它.如果左侧被声明为,我可以理解错误var.
我在这里错过了什么?
编辑:
我接受詹姆斯·冈特的解释.也许只是为了说清楚.我可以很好地阅读编译器规范.我想了解原因.为什么有人决定以这种方式编写规范.这种设计背后必然有一个原因.根据詹姆斯的说法,设计原则是"毫无意外".此外,CodeInChaos还解释了如果编译器试图从常见的祖先中推断出类型,您可能遇到的惊喜.
考虑一下:
module Module1 =
type A() = class end
type B() = inherit A()
type C() = inherit A()
let f x = if x > 0 then new B() else new C()
Run Code Online (Sandbox Code Playgroud)
最后一行产生关于预期类型B的错误,但是找到了类型C. 好吧,我可以假装理解:编译器不知道在有多少公共基础的情况下推断出来.
但猜猜怎么了?即使我指定了函数类型,它仍然不起作用:
let f x : A = if x > 0 then new B() else new C()
Run Code Online (Sandbox Code Playgroud)
现在这给了我两个错误:" A expected,B found "和" A expected,C found ".WTF?为什么不能看到B和C都可以隐式转换为A?
是的,我知道我可以使用upcast,就像这样:
let f x : A = if x > 0 then upcast new B() else upcast …Run Code Online (Sandbox Code Playgroud)