Unable to cast one anonymous type to another
I can't cast one anonymous type to another. A开发者_如何学Cnd I wonder why.
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;
}
}
The exception
Unable to cast object of type '<>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]'.
UPDATE:
is there any way to avoid this exception except using Tuple<decimal.....>
or using one assembly?
Anonymous types are bound to the assembly (technically, the module) that they are declared in. My guess is that this code is in different assemblies. Thus they are completely different types that happen to look similar.
Note that dynamically generated code (ASP.NET pages etc) will be in a different assembly.
By the way, this trick is called "cast by example", and it works fine (just tested it) as long as the types are in the same assembly.
Here it is working, because it is all in one assembly:
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;
}
}
As you can tell from the error message, the compiler has generated 2 distinct types. f__AnonymousType1
and f__AnonymousType0
. And they are in no way related.
The fact that they contain (exactly) the same properties is a coincidence, the compiler will not cast between two 'same' types. They have to be related.
The same problem without Anonymous Types:
class A1
{
public int Id { get; set; }
}
class A2
{
public int Id { get; set; }
}
A1 a = new A1();
A2 b = (A2) a; // error
Error 1 Cannot convert type 'MyApp.A1' to 'MyApp.A2'
But if you are using C#4, do take a look at Tuple<T1,T2,T3,T4,T5,T6>
. It should let you do the same thing or at least something similar.
if you look at the exception you'll see they are two different types. One does not derive from the other.
The specifications says:
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
Taken from the error message you have to different types that both derive from object. So why would you expect to be able to cast from one to the other?
if you had
class foo<T1,T2,T3,T4,T5,T6>{
T1 Item1
T2 Item2
T3 Item3
T4 Item4
T5 Item5
T6 Item6
}
and
class Bar<T1,T2,T3,T4,T5,T6>{
T1 Item1
T2 Item2
T3 Item3
T4 Item4
T5 Item5
T6 Item6
}
would you also expect to be able to cast between those two?
the only difference is the name of the types. Mine are called Foo and Bar yours <>f_AnonymousType1 and <>f_AnonymousType0
These are technically 2 completely separate classes. You can't just cast between 2 classes because they look like each other. For the language, it would be equally impossible as trying to convert a double to a button. If you use c# 4.0 I would suggest using the generic Tuple class, making everything typed. If not, write your own little class to use.
精彩评论