如果返回,我有以下ASP.NET Web Api 2操作和三元组:
[HttpDelete]
public IHttpActionResult Delete()
{
bool deleted;
// ...
return deleted ? this.Ok() : this.NotFound();
}
我收到了
由于存在,因此无法确定条件表达式的类型 'System.Web.Http.Results.OkResult'和。之间没有隐式转换 'System.Web.Http.Results.NotFoundResult'
当他们都实施IHttpActionResult
时。
但是,如果我删除了三元组,编译器很高兴:
if (deleted)
{
return this.Ok();
}
return this.NotFound();
为什么会这样?
答案 0 :(得分:16)
您需要将结果显式地转换为IHttpActionResult
:
return deleted ? (IHttpActionResult) this.Ok() : this.NotFound();
修改强>
至于助学金问题:
为什么Sam的第二个代码块没有明确地转换为 IHttpActionResult,只是出于好奇?这是特别的事吗? 到条件?:运算符?
让我们创建一个简单的演示。 假设以下代码:
public interface IFoo { }
public class B : IFoo { }
public class C : IFoo { }
然后是以下内容:
public class A
{
IFoo F(bool b)
{
return b ? (IFoo) new B() : new C();
}
}
让我们看看编译器如何反编译三元运算符:
private IFoo F(bool b)
{
IFoo arg_13_0;
if (!b)
{
IFoo foo = new C();
arg_13_0 = foo;
}
else
{
arg_13_0 = new B();
}
return arg_13_0;
}
显式强制转换足以让编译器推断变量应该是IFoo
类型,因此满足整个if-else
。这就是为什么它足以让我们提示"提示"编译器只有一次我们的类型转换。
@dcastro引用了确定类型控制的语言规范的确切部分,请参阅文本书定义。
答案 1 :(得分:7)
在三元表达式A? B : C
中,必须有一个引用转换(例如,从基本类型到派生类型,反之亦然)从B到C或C到乙
您希望编译器找到两种类型(IHttpActionResult
)中派生最多的共同祖先 - 编译器不会这样做。
作为一般经验法则,任何表达式的结果类型必须包含在表达式本身中。即,bool? dog : cat
无法返回animal
,因为类型animal
的变量不是表达式的一部分。
来自C#语言规范部分7.14条件运算符:
?:运算符的第二个和第三个操作数x和y控制条件表达式的类型。
- 如果x的类型为X,则y的类型为Y.
- 如果从X到Y存在隐式转换(第6.1节),而不是从Y到X,则Y是条件表达式的类型
- 如果从Y到X存在隐式转换(第6.1节),而不是从X到Y,则X是类型 条件表达。
- 否则,无法确定表达式类型,并发生编译时错误