“无法确定,因为没有隐式转换”,如果返回三元组

时间:2015-01-07 14:48:08

标签: c# .net polymorphism asp.net-web-api2 conditional-operator

如果返回,我有以下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();

为什么会这样?

2 个答案:

答案 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是类型   条件表达。
    •   
    • 否则,无法确定表达式类型,并发生编译时错误
    •   
  •