我在Core 2.2 ASP.NET WebApi控制器中有一个简单的操作,如下所示:
[HttpGet("test123")]
public ActionResult<string> Test123()
{
return new OkResult();
}
这编译得很好,但我想知道OkResult
对象怎么可能转换为ActionResult<string>
?
这些类具有不同的继承链: OkResult -> StatusCodeResult -> ActionResult
而ActionResult<TValue>
只实现IConvertToActionResult
换句话说,ActionResult<string>
不是OkResult
类的基本类型。
如果我手动执行此操作并将代码更改为:
[HttpGet("test123")]
public ActionResult<string> Test123()
{
var a = new OkResult();
var b = a as ActionResult<string>; // Error CS0039
return b;
}
代码不会因转换错误而编译:
错误 CS0039:无法通过引用转换、装箱转换、取消装箱转换、包装转换或空类型转换将类型"Microsoft.AspNetCore.Mvc.OkResult"转换为"Microsoft.AspNetCore.Mvc.ActionResult">
为什么第一个代码有效而第二个代码无效?如何从没有公共基类型的对象转换返回类型?
两个隐式运算符来自ActionResult<TValue>
/// <summary>
/// Implictly converts the specified <paramref name="value"/> to an <see cref="ActionResult{TValue}"/>.
/// </summary>
/// <param name="value">The value to convert.</param>
public static implicit operator ActionResult<TValue>(TValue value)
{
return new ActionResult<TValue>(value);
}
/// <summary>
/// Implictly converts the specified <paramref name="result"/> to an <see cref="ActionResult{TValue}"/>.
/// </summary>
/// <param name="result">The <see cref="ActionResult"/>.</param>
public static implicit operator ActionResult<TValue>(ActionResult result)
{
return new ActionResult<TValue>(result);
}
源
是允许在操作中使用多个返回类型的原因。
[HttpGet("test123")]
public ActionResult<string> Test123() {
if(someCondition) return "String value"; //<--String
return Ok(); //<-- OkResult
}
返回字符串时,将调用ActionResult<TValue>(TValue value)
运算符,返回另一个运算符的有效ActionResult<TValue>
,反之亦然。
您的第一个示例利用了隐式用户定义类型转换运算符,如下所示:
public static implicit operator ActionResult<TValue>(ActionResult result)
{
return new ActionResult<TValue>(result);
}
您的第二个示例使用 as
,无法使用隐式转换运算符,因为根据文档,它:
。仅执行引用转换、可为空转换和装箱转换。as 运算符无法执行其他转换,例如用户定义的转换,而应使用强制转换表达式执行转换。