从 List 中隐式删除泛型参数

本文关键字:删除 泛型 参数 List | 更新日期: 2023-09-27 18:33:30

TL;DR:(标题给出了它(我可以在一次转换中"隐式删除List<T>中的通用参数"吗?

今天一位朋友问我是否可以将List<T>隐式转换为非泛型包装器。

var list = new List<_some_type_>();
ObjectResult result = list;

该方法如下所示:

public static implicit operator ObjectResult(List<T> list) { ... }

显然,这里没有定义T,隐式运算符的方法名是类型名,因此你不能在方法名中包含泛型参数,除非类型实际上是泛型的,即:

class ObjectResult<T> { ... }

而不是

class ObjectResult { ... }

我们对用户定义的转换的约束是(我错过了什么吗?

  1. 无法与基类型相互转换
  2. 无法与接口相互转换。
  3. 必须将转换括在两种类型之一中。

是什么让List<T>如此困难:

  1. List<T>唯一的推导来自Object,因此我们必须直接从List<T>
  2. 同样,List<T>只有接口,必须直接从List<T>
  3. 显然,List<T>是在框架中编译的,因此,它必须来自我们的包装器

我想到了一个两步解决方案,我们可以从一个中间人转换(而唯一有List<T>的中间人是Object,并且由于规则#1,这不是一个选项(。

public class ObjectResult
{
  public static implicit operator ObjectResult(WrapperBase arg) { ... }
}
public class WrapperBase { }
public class ObjectResultWrapper<T> : WrapperBase
{
  public static implicit operator ObjectResultWrapper<T>(List<T> arg) { ... }
}

然后,调用代码将如下所示:

var list = new List<int>();
ObjectResultWrapper<int> wrap = list;
ObjectResult result = wrap;

这并不能真正解决问题,它只是隐式删除T的解决方法(但分两步,而不是一个(。此时,使用帮助程序方法而不是使用用户定义的转换会更容易。

可能有论据反对隐含放弃通用论点的目标 - 我没有其他任何关于他为什么觉得这很重要的东西。简单地认为这是一个学术问题。

从 List<T> 中隐式删除泛型参数

答案是:不,你不能用隐式强制转换来做到这一点。

选择:

我认为最好的办法是静态ObjectWrapper.FromList<T>(List<T>)方法。

包装铸件也是一种选择,尽管没有那么优雅。

声明一个静态的"转换"函数而不是尝试声明一个转换运算符怎么样? 然后你可以使用编译器的类型推断做这样的事情(调用转换方法From(:

List<int> list = new List<int>();
ObjectResult result = ObjectResult.From(list);

From方法可能如下所示:

public class ObjectResult
{
    //...
    public static ObjectResult From<T>(T arg) { return new ObjectResult<T>(arg); }
    //...
}
public class ObjectResult<T> : ObjectResult
{
    //...
    public ObjectResult(T obj) { /* ... some implementation ... */ }
    //...
}