我有一个
List<InputField>
但我需要一个
List<IDataField>
有没有办法在c#中强制转换?或者使用Linq获得相同的结果?
我有两个实现相同接口的类:
interface IDataField { }
class InputField : IDataField { }
class PurchaseField : IDataField { }
此列表来自Linq-to-Sql查询:
List<InputField> list = (from i .... select i).ToList();
答案 0 :(得分:39)
两者.OfType&lt; T&gt;和.Cast&lt; T&gt;将返回T的列表,但这两种方法的含义是不同的。
list.OfType 过滤原始列表并返回T类型的所有项目,并跳过那些不属于该类型的项目。
list.Cast 强制转换原始列表中的所有项目都输入T,并为无法转换为该类型的项目抛出异常。
在你的情况下,两者都会给出相同的结果,但使用.Cast可以更清楚地传达你的意图,所以我建议使用它。
List<InputField> list = (from i .... select i).Cast<IDataField>.ToList();
答案 1 :(得分:11)
List<InputField> raw = (from i .... select i).ToList();
List<IDataField> result = raw.OfType<IDataField>().ToList();
答案 2 :(得分:7)
您也可以使用 List.ConvertAll 。
文档:http://msdn.microsoft.com/en-us/library/73fe8cwf.aspx
示例:
List<IDataField> newList = oldList.ConvertAll(i => i as IDataField);
答案 3 :(得分:5)
由于列表来自
List<InputField> list = (from i .... select i).ToList();
难道你不能只修复“选择i”部分而不是返回IDataField吗? 像这样:
List<InputField> list = (from i .... select (IDataField)i).ToList();
如果这不起作用,IEnumerable的“Cast”扩展可能会起作用:
List<DataField> list2 = list.Cast<IDataField>();
答案 4 :(得分:3)
以防万一:我的C#体验很少,但如果这种通用结构与Java相同,那么必须创建一个由超类型参数化的全新List。换句话说,如果Bangle
的每个实例也是Akthud
的实例,则不会跟随每个List<Bangle>
也是List<Akthud>
原因是您可以对此List<Bangle>
进行两次引用。如果第二个引用强制转换然后将其引用为List<Akthud>
,则允许向其添加Akthud
- 但现在第一个引用具有List<Bangle>
,其成员不是全部Bangle
秒。违反!
话虽这么说,大卫B的答案确实应该做到你想要的,正确的,AFAICT。 (看起来像是一个复制操作。)
[如果我误解了C#泛型的语义,我希望有人在评论中纠正我!]
答案 5 :(得分:1)
我不知道直接演员会产生预期效果。我做过这种情况很少见,通常是这样的:
List<InputField> list = .....
List<IDataField> list2 = new (List<IDataField>((IDataField[])list.ToArray()));
答案 6 :(得分:1)
ConvertAll似乎是一个更好的解决方案,因为它不依赖于Linq库,而且更短更直观。
但他们两个都是解决方案,而不是解决方案。它们都创建了具有相同数据的新集合。应该支持.net中的通用协方差,即通用集合中的向上转换,这将允许您自然地这样做。例如:
List<IDataField> ls = (List<IDataField>)List<InputField>
从我的搜索到目前为止,我的结论是.Net从3.5开始不支持此功能。因此,我们最终必须采用变通方法。
以下是关于该主题的讨论:
答案 7 :(得分:0)
我有以下字符串
var str = "2 4 7 8 10";
当我按如下方式投射时
var numbersInt2 = numbers.Split(' ')
.ToList().Cast<int>().ToList();
它返回一个异常,但是
System.InvalidCastException:'指定的转换无效。
(如果使用以下
)var numbersInt = numbers.Split(' ')
.ToList().ConvertAll(int.Parse);
有效。