"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。以前,它是基于操作数的类型;它们必须相等,或者一个操作数必须可以隐式转换为另一个。