"Cannot be determined because there is no implicit conversion" 如果 return 用三元组
"Cannot be determined because there is no implicit conversion" with ternery if return
我有以下 ASP.NET Web Api 2 个操作,如果返回:
[HttpDelete]
public IHttpActionResult Delete()
{
bool deleted;
// ...
return deleted ? this.Ok() : this.NotFound();
}
我收到了
Type of conditional expression cannot be determined because there is
no implicit conversion between 'System.Web.Http.Results.OkResult' and
'System.Web.Http.Results.NotFoundResult'
当他们都实施 IHttpActionResult
.
但是,如果我删除三元 if,编译器会很高兴:
if (deleted)
{
return this.Ok();
}
return this.NotFound();
这是为什么?
您需要将结果显式转换为 IHttpActionResult
:
return deleted ? (IHttpActionResult) this.Ok() : this.NotFound();
编辑:
关于 Grants 问题:
Why does Sam's second block of code work without explicitly casting to
IHttpActionResult, just out of curiosity? Is this something particular
to the conditional ?: operator?
让我们创建一个简单的演示。
假设以下代码:
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
。这就是为什么我们 "hint" 编译器只对我们的类型进行一次转换就足够了。
@dcastro 引用了确定类型控制的语言规范的确切部分,请参阅教科书定义。
在三元表达式 A? B : C
中,必须存在来自任一 B 的 引用转换 (例如,从基类型到派生类型,反之亦然)到 C 或 C 到 B.
您希望编译器找到两种类型的派生程度最高的共同祖先(即 IHttpActionResult
)- 编译器不会那样做。
根据一般经验,任何表达式的结果类型都必须包含在表达式本身中。即,bool? dog : cat
不能 return 和 animal
,因为没有 animal
类型的变量是表达式的一部分。
来自 C# 语言规范第 7.14 节条件运算符:
The second and third operands, x and y, of the ?: operator control the type of the conditional expression.
- If x has type X and y has type Y then
- If an implicit conversion (§6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression
- If an implicit conversion (§6.1) exists from Y to X, but not from X to Y, then X is the type of the
conditional expression.
- Otherwise, no expression type can be determined, and a compile-time error occurs
从 C# 9.0 开始,OP 的示例将 成功编译 ,因为三元条件表达式的结果类型现在是 based on the target type。以前,它是基于操作数的类型;它们必须相等,或者一个操作数必须可以隐式转换为另一个。
我有以下 ASP.NET Web Api 2 个操作,如果返回:
[HttpDelete]
public IHttpActionResult Delete()
{
bool deleted;
// ...
return deleted ? this.Ok() : this.NotFound();
}
我收到了
Type of conditional expression cannot be determined because there is no implicit conversion between 'System.Web.Http.Results.OkResult' and 'System.Web.Http.Results.NotFoundResult'
当他们都实施 IHttpActionResult
.
但是,如果我删除三元 if,编译器会很高兴:
if (deleted)
{
return this.Ok();
}
return this.NotFound();
这是为什么?
您需要将结果显式转换为 IHttpActionResult
:
return deleted ? (IHttpActionResult) this.Ok() : this.NotFound();
编辑:
关于 Grants 问题:
Why does Sam's second block of code work without explicitly casting to IHttpActionResult, just out of curiosity? Is this something particular to the conditional ?: operator?
让我们创建一个简单的演示。 假设以下代码:
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
。这就是为什么我们 "hint" 编译器只对我们的类型进行一次转换就足够了。
@dcastro 引用了确定类型控制的语言规范的确切部分,请参阅教科书定义。
在三元表达式 A? B : C
中,必须存在来自任一 B 的 引用转换 (例如,从基类型到派生类型,反之亦然)到 C 或 C 到 B.
您希望编译器找到两种类型的派生程度最高的共同祖先(即 IHttpActionResult
)- 编译器不会那样做。
根据一般经验,任何表达式的结果类型都必须包含在表达式本身中。即,bool? dog : cat
不能 return 和 animal
,因为没有 animal
类型的变量是表达式的一部分。
来自 C# 语言规范第 7.14 节条件运算符:
The second and third operands, x and y, of the ?: operator control the type of the conditional expression.
- If x has type X and y has type Y then
- If an implicit conversion (§6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression
- If an implicit conversion (§6.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.
- Otherwise, no expression type can be determined, and a compile-time error occurs
从 C# 9.0 开始,OP 的示例将 成功编译 ,因为三元条件表达式的结果类型现在是 based on the target type。以前,它是基于操作数的类型;它们必须相等,或者一个操作数必须可以隐式转换为另一个。