隐式删除List <t> </t>中的泛型参数

时间:2012-05-07 23:23:08

标签: c#

TL; DR :(标题告诉我)我可以“在一次转换中隐式删除List<T>”中的泛型参数吗?

今天有朋友问我是否可以将List<T>隐式转换为非通用包装。

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

该方法看起来像这样:

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

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

class ObjectResult<T> { ... }

而不是

class ObjectResult { ... }

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

  1. 无法转换为基本类型或来自基本类型
  2. 无法转换为接口或从接口转换。
  3. 必须将转换括在两种类型之一中。
  4. 是什么让List<T>变得如此艰难:

    1. List<T>的唯一推导来自Object;因此我们必须直接从List<T>
    2. 转换
    3. List<T>只有接口,同样必须直接来自List<T>
    4. 显然,
    5. List<T>是在框架中编译的,因此,它必须来自我们的包装器
    6. 我想到了一个两步解决方案,其中有一个中间人我们可以转换(而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的工作(但是分两步,而不是一步)。此时,使用辅助方法更容易,而不是使用用户定义的转换。

      可能存在反对隐含放弃泛型论证的目标的论点 - 我没有其他任何他认为这很重要的原因。考虑这只是一个学术问题。

2 个答案:

答案 0 :(得分:2)

答案:不,你不能用隐式演员表达。

备选方案:

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

包装演员也是一个选项,虽然不是那么优雅。

答案 1 :(得分:1)

如何声明静态“转换”功能而不是尝试声明转换运算符?然后你可以使用编译器的类型推断做这样的事情(调用转换方法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 ... */ }
    //...
}