2011-08-11 175 views
3

我無法將一個匿名類型轉換爲另一個匿名類型。我想知道爲什麼。無法將一個匿名類型轉換爲另一個匿名類型

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; 
    } 
} 

異常

無法轉換 類型「<> 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,系統的目的.Decimal]」。

enter image description here

UPDATE: 有什麼辦法避免這種例外,除了使用Tuple<decimal.....>或使用一個組裝?

回答

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; 
    } 
} 
+0

我的代碼位於不同的程序集中。我認爲這是例外的原因。 – Alexandre

+0

如果這些類型在同一個程序集中,那麼這個類型是多餘的,所以是的。但是,除非你正在施放對象或其他重複施放(施放爲相同類型),否則使用匿名類型施放時將失去運氣 –

+1

@Alex如果它位於不同的裝配體中,則我知道***它是原因。匿名類型的類型等價只適用於同一個程序集。考慮使用一個命名類型 - 也許是'Tuple.Create(...)'等 –

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>。它應該讓你做同樣的事情,或者至少類似的事情。

+0

在語言規範它完全闡明,兩個匿名類型在同一順序相同的名稱和類型的*會*同類型,除非(請參閱我的回答); p –

+1

不,我不同意;這是一個**不同的問題。在某些限制下,Cast-by-example可以正常工作。這不是一個好主意,但它有效。 –

+0

好的,我沒有調查_why_他們是不同的類型。你可能對不同的程序集是正確的。 –

0

這在技術上是完全2單獨的類。你不能只在兩個班級之間施放,因爲他們彼此相像。對於這種語言,嘗試將double轉換爲button同樣不可能。 如果你使用c#4.0,我會建議使用通用的Tuple類,使所有的輸入。 如果不是,請編寫您自己的小班使用。

+0

如果它們在同一個程序集***中它們將是***相同的類型(在C#規範中有保證) - 期望在這裏不是不合理的,只是其中一個注意事項沒有滿足。 –

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你<> F_ AnonymousType1和<>˚F _AnonymousType0

+1

「你爲什麼這麼認爲......」 - 因爲語言規範正式聲明(在一定的範圍內),這可以保證工作。期望不是沒有道理的 - 簡而言之,這些限制並未得到滿足。 –

+1

@Marc Gravel你可能是對的,因爲我記得他們說的規格說明,在特定的範圍內,生成的類型將不會相互衍生或相互轉換。我記得不正確如果你有的話,我會喜歡這個規範的參考。在這個假設看到這兩種類型是不一樣的(當然這將使「鑄造」成爲可能)我說我的問題 –

+0

以及這很接近:http://msdn.microsoft.com/en-us/library/ ms364047(v = vs.80).aspx#cs3spec_topic6「在同一個程序中,兩個匿名對象初始值設定項指定相同名稱和類型的相同順序的屬性序列將產生相同匿名類型的實例。包括屬性的順序,因爲它在某些情況下是可觀察的和重要的,如反射。)「 - 雖然這不是規範文檔,在現實中,「程序」應該讀作「程序集」 –