2

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

今天一位朋友问我是否可以将 a 隐式转换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. 无法转换为 Base 类型或从 Base 类型转换
  2. 无法转换为接口或从接口转换。
  3. 必须将转换包含在两种类型之一中。

是什么让List<T>这么难:

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

我想到了一个两步解决方案,其中有一个我们可以转换的中间人(而唯一的中间人List<T>is 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隐式删除的解决方法(但分两步,而不是一步)。在这一点上,有一个辅助方法会更容易,而不是使用用户定义的转换。

可能存在反对隐含放弃通用论点的目标的论点——我没有其他任何关于他为什么认为这很重要的东西。认为这只是一个学术问题。

4

2 回答 2

2

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

备择方案:

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

wrapper cast 也是一种选择,虽然没有那么优雅。

于 2012-05-08T00:18:47.200 回答
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 ... */ }
    //...
}
于 2012-05-08T02:13:50.293 回答