如果返回,"无法确定,因为没有隐含的转换"

Sam*_*ach 15 .net c# polymorphism conditional-operator asp.net-web-api2

如果返回,我有以下ASP.NET Web Api 2动作和三元组:

[HttpDelete]
public IHttpActionResult Delete()
{
    bool deleted;

    // ...

    return deleted ? this.Ok() : this.NotFound();
}
Run Code Online (Sandbox Code Playgroud)

我收到了

无法确定条件表达式的类型,因为'System.Web.Http.Results.OkResult'和'System.Web.Http.Results.NotFoundResult'之间没有隐式转换

什么时候他们都实施IHttpActionResult.

但是,如果我删除了三元组,编译器很高兴:

if (deleted)
{
    return this.Ok();
}
return this.NotFound();
Run Code Online (Sandbox Code Playgroud)

为什么是这样?

Yuv*_*kov 19

您需要将结果显式地转换为IHttpActionResult:

return deleted ? (IHttpActionResult) this.Ok() : this.NotFound();
Run Code Online (Sandbox Code Playgroud)

编辑:

至于拨款问题:

为什么Sam的第二个代码块没有明确地转换为IHttpActionResult,只是出于好奇?这是条件?:运算符特有的吗?

让我们创建一个简单的演示.假设以下代码:

public interface IFoo { }

public class B : IFoo { }

public class C : IFoo { }
Run Code Online (Sandbox Code Playgroud)

然后是以下内容:

public class A
{
    IFoo F(bool b)
    {
        return b ? (IFoo) new B() : new C();
    }
}
Run Code Online (Sandbox Code Playgroud)

让我们看看编译器如何反编译三元运算符:

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;
}
Run Code Online (Sandbox Code Playgroud)

显式转换足以让编译器推断出变量应该是类型IFoo,从而满足我们的整体if-else.这就是为什么我们只能在我们的类型转换中"提示"编译器一次就足够了.

@dcastro引用了确定类型控制的语言规范的确切部分,请参阅文本书定义.

  • @GrantWinney我的意思是如果你不投,三元无法确定表达式的返回类型.假设他们都实现了'IBar`和`IFoo`,应该返回类型为`IBar`或`IFoo`?编译器无法知道并且无法选择随机类型. (3认同)
  • @GrantWinney的底线是可能有两种类型都实现的其他类型,所以你需要告诉编译器你想要转换哪种类型.例如,如果它们都实现了也是有效的IFoo接口转换.在if语句中不是这种情况,因为编译器知道返回类型. (2认同)
  • @GrantWinney如果你完全忘记了方法的返回类型,那么更容易理解发生了什么.表达式是独立评估的.问题是,如果`a`和`b`同时实现了`IFoo`和`IBar`,那么在这个语句中会出现什么类型的`x`:`var x = bool?a:b` (2认同)

dca*_*tro 8

在三元表达式中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是条件表达式的类型.
    • 否则,无法确定表达式类型,并发生编译时错误