Как использовать оператор слияния нулей с ActionResult ASP.NET Core 2.1 - PullRequest
0 голосов
/ 04 февраля 2019

Может кто-нибудь объяснить мне, почему я получаю сообщение об ошибке слияния нуля по следующему методу:

private readonly Product[] products = new Product[];

[HttpGet("{id}")]
public ActionResult<Product> GetById(int id)
{
    var product = products.FirstOrDefault(p => p.Id == id);
    if (product == null)
        return NotFound(); // No errors here
    return product; // No errors here

    //I want to replace the above code with this single line
    return products.FirstOrDefault(p => p.Id == id) ?? NotFound(); // Getting an error here: Operator '??' cannot be applied to operands of type 'Product' and 'NotFoundResult'
}  
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Category { get; set; }
    public decimal Price { get; set; }
}

Что я не понимаю, так это то, почему первые возвраты работают без необходимости какого-либо приведения, в то время как вторая объединяющая нуль-слияние одной строки не работает!

Я нацеливаюсь на ASP.NETCore 2.1

Редактировать: Спасибо @ Хасан и @ dcastro за объяснения, но я не рекомендую использовать здесь объединение нулей, так как NotFound() не вернет правильноекод ошибки после приведения!

return (ActionResult<Product>)products?.FirstOrDefault(p => p.Id == id) ?? NotFound();

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019
[HttpGet("{id}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
public ActionResult<Product> GetById(int id)
{
    if (!_repository.TryGetProduct(id, out var product))
    {
        return NotFound();
    }

    return product;
}

В предыдущем коде код состояния 404 возвращается, когда товара нет в базе данных.Если продукт существует, возвращается соответствующий объект Product.До ASP.NET Core 2.1 возвращаемый продукт;строка была бы возвращена Ok (product);.

Как видно из приведенного выше кода и объяснения из связанной с Microsoft страницы , после .NET Core 2.1 вам не нужновернуть точный тип в контроллере (ActionResult<T>), как раньше.Чтобы использовать эту функцию, вам нужно добавить атрибуты для указания возможных типов ответов, таких как [ProducesResponseType(200)] и т. Д.

В вашем случае вам нужно просто добавить соответствующие атрибуты типа ответа в метод контроллера, как показано ниже (поскольку вы разрабатываете с .NET Core 2.1).

[HttpGet("{id}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
public ActionResult<Product> GetById(int id)

Редактировать:

Причина, по которой вы не можете скомпилировать программу (используйте оператор объединения нулей), заключается в том, что возвращаемые типы не являются конкурентными.В одном случае он возвращает класс продукта, в противном случае он возвращает ActionResult<T>.После обновления кода, как я и предлагал, я полагаю, вы сможете использовать оператор объединения нулей.

2.Edit (здесь ответили)

После более глубокого изучения проблемы я обнаружил, что при использовании троичных операторов if или оператора нулевого слияния нам нужно явно указать, какой тип мы ожидаембыть произведенным из этого оператора, когда несколько типов возможно могут быть возвращены.Как уже было сказано здесь , компилятор не решает, какой тип он возвращает, без явного его приведения.Таким образом, приведение типа возврата к ActionResult решает проблему.

return (ActionResult<Product>) products.FirstOrDefault(p=>p.id ==id) ?? NotFound();

Но лучше добавить атрибуты типа ответа, как показано выше.

0 голосов
/ 04 февраля 2019

Ошибка возникает из-за невозможности приведения типов.

Попробуйте это:

[HttpGet("{id}")]
public ActionResult<Product> GetById(int id)
{
    var result = products?.FirstOrDefault(p => p.Id == id);
    return result != null ? new ActionResult<Product>(result) : NotFound();
}
...