[英]How to use null-coalescing operator with ActionResult ASP.NET Core 2.1
有人可以解释一下为什么我在以下方法的空合并上出现错误:
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.NET Core 2.1
编辑:感谢@Hasan和@dcastro的解释,但我不建议在此处使用空合并,因为NotFound()
在转换后不会返回正确的错误代码!
发生错误是因为无法转换类型。
尝试这个:
[HttpGet("{id}")]
public ActionResult<Product> GetById(int id)
{
var result = products?.FirstOrDefault(p => p.Id == id);
return result != null ? new ActionResult<Product>(result) : NotFound();
}
[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)
编辑:
无法编译程序(使用null运算符)的原因是返回类型不具有竞争力。 在一种情况下,它将返回产品类,否则将返回ActionResult<T>
。 按照我的建议更新代码后,我想您将可以使用null-coalescing运算符。
2.编辑 (在此处回答)
在更深入地研究问题之后,我发现当使用三元if语句或null合并运算符时,当可能返回多种类型时,我们需要明确指定期望从该语句中生成哪种类型。 如前问这里 ,编译器并不能决定它返回一个类型毫不隐晦地浇铸。 因此,将返回类型强制转换为ActionResult即可解决问题。
return (ActionResult<Product>) products.FirstOrDefault(p=>p.id ==id) ?? NotFound();
但是最好添加响应类型属性,如上所示。
OP 的问题可以分为两部分:1) 为什么建议的空合并表达式不能编译,以及 2) 在 ASP.NET Core 2.1 中是否有另一种简洁的(“单行”)方式返回结果?
如@Hasan 答案的第二次编辑所示, 空合并运算符的结果类型是根据操作数类型而不是目标类型来解析的。 因此,OP 的示例失败了,因为Product
和NotFoundResult
之间没有隐式转换:
products.FirstOrDefault(p => p.Id == id) ?? NotFound();
@Kirk Larkin 在评论中提到了一种在保持简洁语法的同时修复它的方法:
products.FirstOrDefault(p => p.Id == id) ?? (ActionResult<Product>)NotFound();
从 C# 8.0 开始,您还可以使用switch 表达式:
products.FirstOrDefault(p => p.Id == id) switch { null => NotFound(), var p => p };
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.