C# 隐式从列表中删除泛型参数<;T>;
TL;DR:(标题给出了它)我能在一次转换中“隐式地从C# 隐式从列表中删除泛型参数<;T>;,c#,C#,TL;DR:(标题给出了它)我能在一次转换中“隐式地从列表中删除泛型参数吗?” 今天一位朋友问我是否可以将列表隐式转换为非通用包装 var list = new List<_some_type_>(); ObjectResult result = list; 而不是 class ObjectResult { ... } 我们对用户定义转换的限制是(我是否缺少任何限制?) 无法转换为基类型或从基类型转换 无法转换到接口或从接口转换 必须将转换包含在两种类型之一中 是什么让列表变得如
列表中删除泛型参数吗?”
今天一位朋友问我是否可以将列表
隐式转换为非通用包装
var list = new List<_some_type_>();
ObjectResult result = list;
而不是
class ObjectResult { ... }
我们对用户定义转换的限制是(我是否缺少任何限制?)
无法转换为基类型或从基类型转换
无法转换到接口或从接口转换
必须将转换包含在两种类型之一中
是什么让列表变得如此困难:
列表
的唯一派生来自对象
;因此,我们必须直接从List
List
只有接口,而且必须直接从List
列表
显然是在框架中编译的,因此,它必须来自我们的包装器
我想到了一个两步解决方案,其中有一个我们可以转换的中间人(而只有列表
的中间人是对象
,根据规则1,这不是一个选项)
公共类ObjectResult
{
公共静态隐式运算符ObjectResult(WrapperBase arg){…}
}
公共类包装器基{}
公共类ObjectResultRapper:WrapperBase
{
公共静态隐式运算符ObjectResultRapper(列表参数){…}
}
然后,调用代码如下所示:
public static implicit operator ObjectResult(List<T> list) { ... }
var list = new List<int>();
ObjectResultWrapper<int> wrap = list;
ObjectResult result = wrap;
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 ... */ }
//...
}
var list=newlist();
ObjectResultRapper wrap=列表;
ObjectResult=wrap;
这并不能真正解决问题,它只是隐式删除t
的一种变通方法(但分两步,而不是一步)。在这一点上,有一个helper方法会更容易,而不使用用户定义的转换
可能有人反对隐式删除通用论点的目标——我不知道他为什么认为这很重要。考虑这只是一个学术问题。 答案:<强>不,不能用隐式转换来实现。< /强>
备选方案:
我认为最好是一个静态ObjectWrapper.FromList(List)
方法
包装器强制转换也是一个选项,尽管没有那么优雅。不如声明一个静态的“Convert”函数,而不是尝试声明一个转换运算符?然后,您可以使用编译器的类型推断执行如下操作(从
调用转换方法):
不能从任何接口转换似乎是一个非常奇怪的要求<代码>列表
实现了非泛型的IList,它不需要
知识。我希望您指出了对该语言的要求-这些不是我编造的。。。只是澄清一下你的评论是针对语言的,而不是我:)你能解释一下你到底想做什么吗?ObjectResult
的意义是什么?我不明白——如果您想要一个从通用列表派生的非通用列表
,为什么不作为IList
与之交互?这正是它的目的。@svick和KirkWoll再一次,我在学术上接近这个目标,不是因为某个结果目标。这是一个平淡的问题,寻找平淡的答案(是否可能…)。是的,有IList,但问题不是“是否存在列表
的非泛型句柄?”在我的第二条规则中,我提到了不允许接口转换,至少这是我从编译器得到的:“Testing.ObjectResult.implicit operator Testing.ObjectResult(System.Collections.generic.IEnumerable)“:不允许与接口进行用户定义的转换。我使用的是.net 4.0和visual studio 2010compiler@payo:嗯,看来你不能那么做。更新的答案。我同意静态方法可能是这里最好的解决方案。但我不建议使用双重强制转换,它太复杂和混乱了。我同意更优雅的解决方案是使用实用程序(比如静态强制转换)。但同样,这个问题更多的是在语言中寻找什么是可能的。我为我的固执道歉——但我已经说过很多次了,所以人们总是想修正你的方法,而不是回答问题。有时候我们只是在寻找可能的东西,即使我们的测试用例很差。@payo:我也注意到了,我真的很讨厌人们不起来回答问题。在这种情况下,qestion似乎是不可能的。我同意这是一个更优雅的解决方案。看来,这个问题的具体目标是不可能实现的。
var list = new List<int>();
ObjectResultWrapper<int> wrap = list;
ObjectResult result = wrap;
List<int> list = new List<int>();
ObjectResult result = ObjectResult.From(list);
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 ... */ }
//...
}