簡體   English   中英

將約束的通用類型傳遞給非通用方法

[英]Passing Constrained Generic Type to Non-Generic Method

為什么我不能傳遞此類的實例...

class Item<T> where T : Thing { }

...變成這種方法:

void DoSomething(Item<Thing> item);

由於我已將Item<T>約束為Item<Thing> ,因此在將我的項目發送到DoSomething之前應該可以安全地進行轉換-但是為什么框架不處理此問題呢?

假設您有一堂課:

public class SomeOtherThing : Thing { }

無法Item<SomeOtherThing>轉換為Item<Thing> 她們不一樣。

讓我們暫時假設項目看起來像這樣:

public class Item<T>
{
    public T Value { get; set; }
}

然后, DoSomething可能會執行以下操作:

void DoSomething(Item<Thing> item)
{
    item.Value = new Thing();
}

如果將Item<SomeOtherThing>傳遞給DoSomething您現在剛剛將一個新的Thing分配給Value但是value是SomeOtherThing類型的屬性,則無法為其設置Thing對象 這樣會破壞類型系統。 編譯器知道這是一個選擇。 因此(以及具有相同基本問題的許多其他操作),不能將Item<SomeOtherThing>轉換為Item<Thing>

所以,你可以做什么?

好吧,如果您控制DoSomething的定義,也許它也應該是通用的。

如果DoSomething看起來像這樣:

void DoSomething<T>(Item<T> item)
    where T : Thing
{    }

然后,您可以使用Item<SomeOtherThing>進行調用,因為以前可能導致問題的操作在DoSomething不再有效。

想像

class Derived : Thing {}

無法將Item<Derived>分配給Item<Thing>

您需要像這樣在方法聲明中更具體一些;

void DoSomething<T>(Item<T> item)
    where T : Thing
{
    // now your method knows that T must be of time Thing and you can use it
}

您遇到的問題是您的方法特定於Item<Thing> ,而Item<Something>不是有效的參數。 C#不支持通用類協方差。 您有幾種選擇。

“最簡單”的事情就是簡單地使您的方法通用,並為Thing添加約束。 這將是第一個建議的方法。

void DoSomething<T>(Item<T> item) where T : Thing
{
}

這將授予您訪問Thing所有成員(如果適用)的權限,同時仍然擁有可以滿足所有子類的方法。

另一個有更多限制的選項是讓Item<Thing>的非通用基礎就是Item (在其中,無論您以前暴露T的哪個位置,都將暴露object 。請考慮: IEnumerable<T>IEnumerable 。)

void DoSomething(Item item)
{
}

您的方法只需要Item ,就可以使用它。 但是,如果您有使用Thing的特定要求,那么它會更加微妙,您需要進行適當的轉換,但同時也面臨着有人傳遞的實例不是 Item<T>的可能性,其中T是一個東西。

另一種選擇是不保留方法的簽名,並將其從類轉換為接口,從而允許您使用協方差。 (.NET 4.0在接口和委托類型中支持Co / contravariance。)

interface Item<out T> 
{
    T Get();
    // void Set(T foo); // invalid  
}

同樣,這里的問題是:1)(顯然)您需要更改類型,但是2)您將只能在輸出位置暴露T 注意,支持Get()方法。 Set(T)方法不是,因為T是輸入,這使得該接口不是協變有效的。 (想象一下傳入一個Item<Something> ,並且您的方法嘗試使用SomeOtherThing調用Set 。兩者都是Things ,但是顯然第二個不適用於第一個。)因此,如果您需要同時支持T作為輸出輸入,則無法利用這種方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM