2011-07-15 187 views
7

當我們有這樣的事情:如何不指定任何類型創建構造泛型類型參數

interface ISomething<U,V> { ... } 
class Something<U,V> : ISomething<U,V> { ... } 

typeof(ISomething<,>)typeof(Something<,>)將導致「泛型類型定義」。但是,如果我們得到的接口類型由類實現的接口,這將是一個構造類型,即沒有其類型參數的實際約束:

typeof(Something<,>).GetInterfaces().SingleOrDefault() 

MSDN特別提到了這一點。我想要的是直接構造ISomething<,>的相同類型(構造類型)(沒有子類並且他們在尋找基類型),並且我找不到任何方法來這樣做。

附加信息:

我甚至試過這樣:

Type t1 = typeof(ISomething<,>); 
Type t2 = t1.MakeGenericType(t1.GetGenericArguments()) // Yields a generic type definition 

Type t3 = typeof(Something<,>).GetInterfaces().SingleOrDefault(); 

在上面的代碼:

t1.Equals(t2)是真實的,但t1.Equals(t3)是假的,顯然是因爲t3構造。

令人驚訝的是,t1.GetGenericArguments()[0].Equals(t3.GetGenericArguments()[0])是假的,雖然都是開放的(IsGenericParameter = true),我找不到它們的屬性有任何區別。

這就是爲什麼我需要這樣做:我需要在列表中存儲Type對象的規範形式。這些對象有時來自基類/接口(如上面的t3),有時來自直接的(如t1)。我需要能夠比較這些對方。我不能存儲泛型類型定義(使用.GetGenericTypeDefinition()),因爲有時我會有一個部分打開的構造泛型類型(如ISomething),並且GetGenericTypeDefinition將給我一個沒有指定任何類型參數的類型。

使我認爲可能工作的規範類型的唯一方法是檢查是否所有類型參數都是未綁定的,並執行GetGenericTypeDefinition。否則保持構造的類型。

+0

我不認爲這個作品:「檢查所有的類型參數是未綁定的,並做一個GetGenericTypeDefinition,否則保持構造的類型。「假設你的類型是'I '。所有的類型參數都是未綁定的類型參數,但與「I '不同。 –

+2

回覆:「令人驚訝的......」 - 這並不令人意外。我懷疑所有這些困惑的一部分是你有兩種完全不同的類型,稱爲「U」,兩種完全不同的類型稱爲「V」。當然'I <,>'與實現的接口列表中的'I '不同;前者用'I'聲明的''參數化,另一個用'Something'聲明的''參數化。僅僅因爲類型參數具有相同的名稱不會使它們成爲相同的類型。 –

+0

如果我有一個構建的'I ',並調用GetGenericTypeDefinition(),它會給我'typeof(I )'? – Iravanchi

回答

4

你讓自己都搞砸了。檢查這個程序的輸出,並確保你瞭解它。在這裏,我的α-更名爲類型參數,這樣就沒有不清晰,由於兩件事情都名爲U:

interface I<S, T> 
{ 
    I<S, T> M(); 
} 

class C<U, V> : I<U, V> 
{ 
    public I<U, V> M() {return null;} 
    public C<U, V> N() {return null;} 
} 

public class MainClass 
{ 
    public static void Main() 
    { 
     var i1 = typeof(I<,>); 
     var i2 = typeof(I<int, int>); 
     var i3 = i2.GetGenericTypeDefinition(); 
     var i4 = i1.GetMethod("M").ReturnType; 

     var c1 = typeof(C<,>); 
     var c2 = typeof(C<int, int>); 
     var c3 = c2.GetGenericTypeDefinition(); 
     var c4 = c1.GetMethod("N").ReturnType; 

     var i5 = c1.GetMethod("M").ReturnType; 
     var i6 = c1.GetInterfaces()[0]; 

     System.Console.WriteLine(i1 == i2); // false -- I<,> is not I<int, int> 
     System.Console.WriteLine(i1 == i3); // true -- I<int,int>'s decl is I<,> 
     System.Console.WriteLine(i1 == i4); // true -- I<,> is I<S, T> 
     System.Console.WriteLine(i1 == i5); // false -- I<S, T> is not I<U, V> 
     System.Console.WriteLine(i1 == i6); // false -- I<S, T> is not I<U, V> 

     System.Console.WriteLine(c1 == c2); // false -- C<,> is not C<int, int> 
     System.Console.WriteLine(c1 == c3); // true -- C<int,int>'s decl is C<,> 
     System.Console.WriteLine(c1 == c4); // true -- C<,> is C<U,V> 
    } 
} 
+0

謝謝埃裏克,你太棒了。我意識到我的錯誤,但你的示例代碼很好。我想我可以通過傳遞類的泛型參數使GenericType離開接口 - 即't1.MakeGenericType(typeof(Something <,>).GetGenericArguments())'來創建我想要的類型。我對嗎? - 雖然,我知道這不會幫助我解決我最初的問題。 – Iravanchi

+0

@不客氣。你不會相信我們必須在編譯器中解決的這類問題。它會變得非常混亂! –

+0

我可以問一個問題嗎?到目前爲止,我還沒有在Genrics上做過多的工作,所以我想知道他們的優點?他們有什麼意義(創造,使用...)? thx的答案 –