"Невозможно определить, потому что нет никакого неявного преобразования" с тернерой, если возвращение
У меня есть следующее действие 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();
Почему это?
Ответы
Ответ 1
Вам нужно явно передать результат на IHttpActionResult
:
return deleted ? (IHttpActionResult) this.Ok() : this.NotFound();
Edit:
Что касается вопроса о грантах:
Почему второй блок кода Сэма работает без явного IHttpActionResult, просто из любопытства? Это что-то конкретное к условному?: 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
. Вот почему нам достаточно "намекнуть" на компилятор только один раз из нашего типа.
@dcastro ссылается на точную часть спецификации языка, которая определяет управление типом, см. это для определения текстовой книги.
Ответ 2
В тройном выражении A? B : C
должно быть референсное преобразование (например, от базового типа к производному типу или наоборот) от B до C или C к B.
Вы ожидали, что компилятор найдет наиболее производный общий предок двух типов (который есть IHttpActionResult
) - компилятор этого не делает.
Как общее правило, тип результата любого выражения должен содержаться внутри самого выражения. I.e., bool? dog : cat
не может вернуть animal
, потому что никакая переменная типа animal
не является частью выражения.
В разделе "Спецификация языка С#" 7.14 "Условный оператор":
Второй и третий операнды, x и y, оператора?: управляют типом условного выражения.
- Если x имеет тип X, а y имеет тип Y, тогда
- Если неявное преобразование (§6.1) существует из X в Y, но не от Y до X, то Y является типом условного выражения
- Если неявное преобразование (§6.1) существует от Y до X, но не от X до Y, то X является типом условное выражение.
- В противном случае тип выражения не может быть определен, и возникает ошибка времени компиляции