2014-02-09 91 views
11

我很迷戀這個,所以如果任何人有任何想法。我有泛型方法在運行時添加通用約束?

public void Foo<TClass>(TClass item) where TClass : class 
{ } 

我想從另一個調用泛型方法這種方法,但這種方法一般不具有類型約束「其中TClass:類」

public void Bar<T>(T item) 
{ 
    this.Foo<T>(item); 
} 

這並未「T工作,我得到的錯誤

‘類型‘T’必須是引用類型,以便將它作爲參數‘TClass’’

我的理解。但我的問題是這樣的 - 有什麼我可以用C#語法做的事情,以便「過濾」泛型類型「T」,如果它是一個類,將它傳遞給「this.Bar」。像....

public void Bar<T>(T item) 
{ 
    if (typeof(T).IsClass) 
     this.Foo<T **as class**>(); 
} 

我意識到我可以使用反射來調用Foo,但這只是看起來像作弊。有什麼我可以用C#做​​到在運行時將約束傳遞給「T」?

而且 - 我不能因爲它從一個接口,這樣的約束有約束相匹配的接口上

+0

您是否將「this.Foo ();」 ? – Euphoric

+0

well spotted - edited :) – jcharlesworthuk

+1

那麼你爲什麼不使用'if(typeof(T).IsClass)'? –

回答

4

調用Foo無反射的唯一方法,就是投item的類型/類中的一個在其層次結構(在適當的IsClass檢查後)。

很明顯,只有一種類型的層次結構,你知道先驗Object

public void Bar<T>(T item) 
{ 
    if (typeof(T).IsClass) 
     this.Foo((object) item); 
} 

編輯:

而且,你說你加入class約束是實例T的意見之一。你不需要那個,你需要的是new constraint

+0

哇,實際上編譯,我完全忘了你可以像這樣的歡呼「快捷」泛型!也是的,你是對的,我確實也有新的約束,但是爲了簡化它而將它留在這個問題之外:) – jcharlesworthuk

-1

我相信沒有辦法讓它編譯改變方法「酒吧」的約束。你將不得不用反射來打電話。

其實。你可以欺騙你,如果它包含一個類中:

public class Container<T> 
    { 
     public Container(T value) 
     { 
      Value = value; 
     } 

     public T Value { get; private set; } 
    } 

    public void Bar<T>(T item) 
    { 
     this.Foo<Container<T>>(new Container<T>(item)); 
    } 

但是這會增加一層,你需要呼通,使各類不太清楚。

+0

因爲'Container '不匹配'Foo (T item)',並且如果您將其更改爲:'Foo (Container item)',它將不起作用,因爲它將仍然會說' T'必須是ref類型。 –

+0

@ Some1Pr0什麼? – Euphoric

+0

他說這行'新容器(item)'不會編譯,因爲類型約束 – jcharlesworthuk

4

不幸的是,如果不將Bar更改爲通用約束class或使用反射,則無法做到這一點。爲了編譯C#必須知道在編譯時T確實是一個class的值。爲了滿足這個編譯時間約束,沒有辦法使用動態測試,如typeof(T).IsClass

您在問題中提到您不能更改Bar,但似乎您願意接受發生動態故障的可能性。也許不是改變Foo不具有約束,而是拋出一個異常時T不是類類型

+0

嗨,謝謝你的回答。我把約束放在「Foo」上,因爲我想用「Foo」來實例化一個新的項目實例。因此,它自己的「Foo」確實需要一個可以通過執行「new T()」來實例化的對象。我寧願在「Bar」中有一個運行時異常而不是「Foo」。但如果反射是唯一的選擇,那麼我猜這就好:) – jcharlesworthuk

0
if (typeof(T).IsClass) 
{ 
    this.GetType() 
     .GetMethod("Foo", System.Reflection.BindingFlags.Instance | 
          System.Reflection.BindingFlags.Public) 
     .Invoke(this, new object[] { item }); 
} 
+0

我很確定他明確詢問是否有替代反射。 – Euphoric