[英]Put a struct as a generic covariant parameter
我有一個 Covariant 接口,它位於它的父類型的數組中。 它們在全局定義如下:
//The interface/class
public interface IMyType<out T>{}
public class MyType<T>: IMyType<T>{
T value;
MyType<T>(T initialValue){
value = initialValue;
}
}
我試過這個:
IMyType< object>[] tt = new IMyType<object>[]
{
new MyType<String>( "test"), //Works fine
new MyType<SomeOtherRandomClass>(new SomeOtherRandomClass()),//works fine
new MyType<Int32>(12)//Doesn't work
};
甚至試圖指定一個結構而不是對象:
IMyType< struct>[] tt = new IMyType<struct>[]//Doesn't work:Incorrect Number of parameter
{
new MyType<Int32>(12)//Doesn't work
};
僅指定特定結構有效:
IMyType< int>[] tt = new IMyType<int>[]//Does work
{
new MyType<Int32>(12)//Does work
};
那么為什么這不起作用呢? 有沒有辦法讓它工作?
將Interface<ValueType>
轉換為Interface<object>
作為協變轉換是完全不可能的。
這樣做的原因是 JITter 必須為每個值類型編譯一個單獨的類版本(因為值類型具有不同的形狀),因此它不能將它轉換為任何其他通用實例化。
方差僅適用於引用類型,因為引用都是相同的,因此 JITted 方法可以在不同的類型參數之間共享。
您最好的解決方案可能是編寫一個封裝結構的包裝類:
public class StructContainer<TStruct> where TStruct : struct
{
TStruct value;
public StructContainer(TStruct initialValue)
{
value = initialValue;
}
}
那么你可以這樣做:
IMyType<object>[] tt = new IMyType<object>[]
{
new MyType<String>("test"), //Works fine
new MyType<StructContainer<int>>(
new StructContainer<int>(12)
) // compiles now
};
誠然,這犧牲了原始語法的簡單性,並迫使您稍后在需要從集合中提取項目時做一些復雜的事情(如類型檢查)。
另一種選擇是將對象集合和結構集合作為單獨的集合進行跟蹤。 這可能更有意義,因為同樣,一旦您將項目從列表中拉出,您可能需要以不同的方式對待它們。
如果你想完成將具有不同類型參數的泛型類型放入同一個集合中,並且由於 SLaks 提到的原因你不能使用協方差,那么你應該讓泛型類型實現一個非泛型接口:
public interface IMyType<out T> : ISomeBaseInterface {}
var tt = new ISomeBaseInterface[]
{
new MyType<String>( "test"), //Works fine
new MyType<SomeOtherRandomClass>(new SomeOtherRandomClass()),//works fine
new MyType<Int32>(12)//now it works
};
根據您的其他要求,這可能足夠也可能不夠。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.