“无法确定,因为没有隐式转换”,如果返回,则使用三元
本文关键字:无法确定 三元 返回 因为 转换 如果 | 更新日期: 2023-09-27 18:36:40
我有以下 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.OkResult"之间没有隐式转换 'System.Web.Http.Results.NotFoundResult'
当他们都实现IHttpActionResult
.
但是,如果我删除三元组,编译器很高兴:
if (deleted)
{
return this.Ok();
}
return this.NotFound();
这是为什么呢?
将结果显式转换为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引用了语言规范中确定类型控制的确切部分,请参阅教科书定义。
在三元表达式A? B : C
中,必须有一个引用转换(例如,从基类型到派生类型,反之亦然)从B到C或C到B。
你希望编译器找到两种类型中最派生的共同祖先(即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 是 条件表达式。
- 否则,无法确定表达式类型,并且会发生编译时错误
从 C# 9.0 开始,OP 的示例将成功编译,因为三元条件表达式的结果类型现在基于目标类型。以前,它基于操作数的类型;它们必须相等,或者一个操作数必须隐式转换为另一个操作数。