当我定义隐式强制转换时,为什么Linq Cast <t>操作失败?</t>

时间:2009-04-30 19:51:51

标签: .net linq casting

我创建了两个类,其中一个类之间有隐式转换:

public class Class1
{
    public int Test1;
}

public class Class2
{
    public int Test2;

    public static implicit operator Class1(Class2 item)
    {
        return new Class1{Test1 = item.Test2};
    }
}

当我创建一个类型的新列表并尝试Cast&lt; T&gt;时另一方面,它失败并出现InvalidCastException:

List<Class2> items = new List<Class2>{new Class2{Test2 = 9}};
foreach (Class1 item in items.Cast<Class1>())
{
    Console.WriteLine(item.Test1);
}

然而,这可以正常工作:

foreach (Class1 item in items)
{
    Console.WriteLine(item.Test1);
}

为什么在使用Cast&lt; T&gt;?

时未调用隐式强制转换

4 个答案:

答案 0 :(得分:6)

因为,通过Reflector查看代码,Cast不会尝试采用任何隐式转换运算符(LINQ Cast代码针对所有类型的特殊情况进行了大量优化,但在该方向上没有任何内容)(与许多.NET语言一样)不会)。

在没有进行反思和其他事情的情况下,仿制药在任何情况下都不提供任何开箱即用的方式来考虑这些额外的东西。

编辑:通常,更复杂的设施,如隐式/显式,等式运算符等,通常不会像LINQ这样的通用设施处理。

答案 1 :(得分:2)

如果需要,您还可以使用此功能进行转换:

public static IEnumerable<TDest> CastAll<TItem, TDest>(this IEnumerable<TItem> items)
{
 var p = Expression.Parameter(typeof(TItem), "i");
 var c = Expression.Convert(p, typeof(TDest));
 var ex = Expression.Lambda<Func<TItem, TDest>>(c, p).Compile();

 foreach (var item in items)
 {
    yield return ex(item);
 }
}

来自http://adventuresdotnet.blogspot.com/2010/06/better-more-type-safe-alternative-to.html

答案 2 :(得分:1)

谢谢你,我准备在某个地方使用那个确切的案例。你救了我一大堆时间。作为问题的可能解决方案,您可以使用ConvertAll&lt;&gt;相反,像这样:

foreach (Class1 item in items.ConvertAll<Class1>((i) => (Class1)i))
{
     Console.WriteLine(item.Test1);
}

编辑:或者如果你想更明确地表明演员是隐含的,那么这也适用:

foreach (Class1 item in items.ConvertAll<Class1>(i => i))
{
     Console.WriteLine(item.Test1);
}

答案 3 :(得分:0)

如果你真的需要这种转换,解决方案可能是在这里使用一点linq'ing:

List items = new List{new Class2{Test2 = 9}};
foreach (Class1 item in (from x in items select (Class1)x))
{
    Console.WriteLine(item.Test1);
}