你可以像这样打包和取消包装类型:
List<object> items = new List<object>();
items.Add("hello");
items.Add(123);
在这里,只要它来自于对象,我们放入什么并不重要。所以这很有效。
但是可以用泛型类来做吗? 像这样:
public class Foo<T>
{
public T MyItem;
}
static void Main()
{
List<Foo<object>> items = new List<Foo<object>>();
items.Add(new Foo<string>() { MyItem = "Hello" });
items.Add(new Foo<int>() { MyItem = 123 });
}
在这里,尽管string和int是对象的类型,但它会给我一个错误。
我想到了一个简单的解决方案,那就是通过转动新的Foo&lt;字符串&gt; 进入新Foo&lt;对象&gt; ,然后只需将字符串值放入对象类型中,如下所示:
items.Add(new Foo<object>() { MyItem = "Hello" });
但是我处在一种我无法做到的情况。
那么有什么办法可以实现这个目标吗?
答案 0 :(得分:3)
鉴于此课程:
public class Foo<T>
{
public T MyItem { get; set; }
}
如果您有Foo<object>
的列表,则无法向其添加Foo<int>
。
如果可以,那么你可以这样做:
var myListOfFoos = new List<Foo<object>>();
myListOfFoos.Add(new Foo<int>());
Foo<object> firstFoo = myListOfFoos[0]; // this is the Foo<int> you added.
firstFoo.MyItem = "string!"; // How can you do this with a Foo<int>?
我的眼睛总是从“协变”和“逆变”这两个词中釉。编译器总是保护您免受这种情况的影响。你只需要弄清楚它是什么(正确地)保护你不要试图去做。
答案 1 :(得分:3)
尝试编译代码:
您必须创建参数T
协变,这只能在接口和委托上完成。将T
定义为协变量时的另一个限制因素是T
不能是值类型。
文档 - out (Generic Modifier) (C# Reference)
对于泛型类型参数,out关键字指定type参数是协变的。您可以在通用接口和委托中使用out关键字。
...参考类型支持协方差和逆变,但 不支持。
关于装箱/拆箱的问题在这种情况下也不适用于泛型。泛型确保类型参数永远不会装箱或取消装箱(默认情况下)。评论中有很多好的链接,我建议你仔细阅读它们,这样你就可以更好地理解1)装箱/拆箱和2)仿制药。
这是您可以使用代码获得的最接近的
static void Main() {
List<IFoo<object>> items = new List<IFoo<object>>();
items.Add(new Foo<string>() { MyItem = "Hello" });
// not possible because int is a value type
// items.Add(new Foo<int>() { MyItem = 123 });
}
interface IFoo<out T>
{
T MyItem {get;}
}
class Foo<T> : IFoo<T>
{
public T MyItem {get;set;}
}