.NET Core 中的泛型 ActionResule<T> 不考虑类型 T

Generic ActionResule<T> in .NET Core doesnot respect the type T

提问人:Gopal Thakur 提问时间:11/10/2023 最后编辑:marc_sGopal Thakur 更新时间:11/11/2023 访问量:85

问:

在下面的示例中,方法的返回类型为GET

ActionResult<SomeAltResult>

但是 return 语句返回 of 并且它仍然编译成功。OKResultIEnumerableWeatherForecast

我无法理解如果我可以返回任何东西,那么拥有泛型有什么意义,我可以使用或.ActionResult<T>ActionResultIActionResult

另外,请帮助我理解不继承任何类或接口链,那么多态性在这里是如何工作的?ActionResult<T>OkObjectResult

namespace WebApplication1.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]{
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm","Balmy", "Hot", "Sweltering", "Scorching"
    };
    
    [HttpGet(Name = "GetWeatherForecast")]
    public ActionResult<SomeAltResult> Get()
    {
        var x = Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
    
        return Ok(x);
    }
}

public class SomeAltResult
{
    public string Name { get; set; }
}
C# ASP.NET-MVC ASP.NET-CORE OOP 多态性

评论


答:

1赞 Mark Seemann 11/11/2023 #1

另外,请帮助我理解不继承任何类或接口链,那么多态性在这里是如何工作的?ActionResult<T>OkObjectResult

该类定义从任何 ActionResult 到 ActionResult<T> 的隐式转换,这解释了它编译的原因。ActionResult<T>

像这样的代码还可以编译:

ActionResult<SomeAltResult> actionResult = Ok(x);

该转换很可能使用将任何 ActionResult 作为输入的构造函数重载。请注意,它不受泛型类型参数的任何约束。因此,您可以使用任何 ,包括 .ActionResultOkObjectResult

我无法理解如果我可以返回任何东西,那么拥有泛型有什么意义,我可以使用或.ActionResult<T>ActionResultIActionResult

这确实是一个奇怪的 API 设计。请考虑 OP 代码的以下变体:

ActionResult<SomeAltResult> actionResult = Ok(x);
SomeAltResult? value = actionResult.Value; // null
return Ok(value);

这也会编译,但 Web 资源现在返回一个空结果。发生这种情况是因为返回,因为它没有 类型的值。actionResult.ValuenullT

我无法解释 API 设计选择。这种无声的失败向我表明了 API 设计缺陷。像这样的代码不应该被允许在没有警告的情况下编译。

尽管如此,OP 仍能正常工作的原因是,ASP.NET 框架唯一关心的是控制器操作是否返回 IActionResult,而 ExecuteResultAsync 方法不关心泛型。它仅将对象隐藏为 HTTP 响应,并且在边界处不存在静态类型IActionResult