无法将一个匿名类型转换为另一个

时间:2011-08-11 11:21:39

标签: c# casting anonymous-types

我无法将一个匿名类型转换为另一个。我想知道为什么。

public static class Class1{
    public static object GetFinance(Guid contractB2CId)
    {
        return new
        {
         Item1 = reader.ValueOrDefault<decimal>(0),
         Item2 = reader.ValueOrDefault<decimal>(1),
         Item3 = reader.ValueOrDefault<decimal>(2),
         Item4 = reader.ValueOrDefault<decimal>(3),
         Item5 = reader.ValueOrDefault<decimal>(4),
         Item6 = reader.ValueOrDefault<decimal>(5)
       };
    }


     object obj = GetFinance();
     var financeInfo = obj.UnsafeCast(new
       {
           Item1 = default(decimal),
           Item2 = default(decimal),
           Item3 = default(decimal),
           Item4 = default(decimal),
           Item5 = default(decimal),
           Item6 = default(decimal)


       });

 } 

     public static class Class2{                                               
     public static T UnsafeCast<T>(this object obj, T type)
     {
       return (T) obj;
     }
} 

例外

  

无法投射类型的对象   。 '&LT;&GT; f__AnonymousType1 6[System.Decimal,System.Decimal,System.Decimal,System.Decimal,System.Decimal,System.Decimal]' to type '<>f__AnonymousType0 6 [System.Decimal,System.Decimal,System.Decimal,System.Decimal,System.Decimal,System.Decimal]'

enter image description here

更新: 有没有办法避免这种异常,除了使用Tuple<decimal.....>或使用一个程序集?

4 个答案:

答案 0 :(得分:7)

匿名类型绑定到声明它们的程序集(技术上,模块)。我的猜测是这个代码在不同的程序集中。因此,它们完全不同,看起来很相似。

请注意,动态生成的代码(ASP.NET页面等)将位于不同的程序集中。

顺便说一句,这个技巧被称为“逐个演员”,只要类型在同一个程序集中,它就可以正常工作(只是测试它)。

这里有效,因为它都在一个程序集中:

static class Program
{
    static void Main()
    {
        object obj = GetFinance();
        var financeInfo = obj.UnsafeCast(new
        {
            Item1 = default(decimal), Item2 = default(decimal),
            Item3 = default(decimal), Item4 = default(decimal),
            Item5 = default(decimal), Item6 = default(decimal)
        });
        System.Console.WriteLine(financeInfo.Item3); // 76
    }
    public static object GetFinance()
    {
        decimal x = 76;
        return new
        {
            Item1 = x, Item2 = x, Item3 = x,
            Item4 = x, Item5 = x, Item6 = x
        };
    }

    public static T UnsafeCast<T>(this object obj, T type)
    {
        return (T)obj;
    }
}

答案 1 :(得分:2)

从错误消息中可以看出,编译器生成了2种不同的类型。 f__AnonymousType1f__AnonymousType0。而且他们没有任何关系。

它们包含(完全)相同属性的事实是巧合,编译器不会在两个“相同”类型之间进行转换。他们必须有关系。

没有匿名类型的同样问题:

class A1
{
    public int Id { get; set; }
}

class A2
{
    public int Id { get; set; }
}


   A1 a = new A1();
   A2 b = (A2) a;    // error 
  

错误1无法将“MyApp.A1”类型转换为“MyApp.A2”

但如果您使用的是C#4,请查看Tuple<T1,T2,T3,T4,T5,T6>。它应该让你做同样的事情或至少类似的东西。

答案 2 :(得分:1)

如果你看一下例外,你会发现它们是两种不同的类型。一个不是来自另一个。

规格说明:

An anonymous type is a nameless class type that inherits directly from object An anonymous type is a nameless class type that inherits directly from object. The members of an anonymous type are a sequence of read/write properties inferred from the object initializer(s) used to create instances of the type. Specifically. Within the same program, two anonymous object initializers that specify a sequence of properties of the same names and types in the same order will produce instances of the same anonymous type

从错误消息中获取您必须从对象派生的不同类型。那么为什么你希望能够从一个投射到另一个呢?

如果你有

class foo<T1,T2,T3,T4,T5,T6>{
T1 Item1
T2 Item2
T3 Item3
T4 Item4
T5 Item5
T6 Item6
}

class Bar<T1,T2,T3,T4,T5,T6>{
T1 Item1
T2 Item2
T3 Item3
T4 Item4
T5 Item5
T6 Item6
}
你还希望能够在这两者之间施展吗?

唯一的区别是类型的名称。我的名字叫做Foo和Bar你的&lt;&gt; f_ AnonymousType1和&lt;&gt; f _AnonymousType0

答案 3 :(得分:0)

这些在技术上是2个完全独立的类。你不能只在两个类之间进行投射,因为它们看起来像是彼此。对于该语言,尝试将双精度转换为按钮同样是不可能的。 如果您使用c#4.0,我建议使用通用的Tuple类,使所有内容都输入。 如果没有,请编写自己的小班以供使用。