逆变代表值类型

时间:2010-06-09 08:45:35

标签: c# c#-3.0 contravariance

任何人都可以阐明为什么逆变不适用于C#值类型?

以下不起作用

private delegate Asset AssetDelegate(int m);

internal string DoMe()
{
    AssetDelegate aw = new AssetDelegate(DelegateMethod);
    aw(32);
    return "Class1";
}

private static House DelegateMethod(object m)
{
    return null;
}

2 个答案:

答案 0 :(得分:5)

问题是 int不是对象

int可以装箱到一个对象。结果对象(也称为boxed int)当然是一个对象,但它不再是一个整数。

请注意,我在上面使用的“ ”与C#运算符is不同。我的“ ”表示“可通过隐式参考转化转换为”。当我们谈论协方差和逆变时,这就是“”的含义。

int可隐式转换为对象,但这不是引用转换。它必须装箱。

House可通过引用转化隐式转换为Asset。无需创建或修改任何对象。

考虑以下示例。变量houseasset都引用了同一个对象。另一方面,变量integerboxedInt具有相同的值,但它们引用了不同的东西。

House house = new House();
Asset asset = house;

int integer = 42;
object boxedInt = integer;

Boxing and Unboxing并不像看起来那么简单。它有许多细微之处,可能会以意想不到的方式影响您的代码。混合拳击与协方差和逆变是一种让任何人炫目的简单方法。

答案 1 :(得分:1)

我同意Anthony Pegram的评论 - 它基于具有与值类型不同的内存占用的引用类型:CLR可以隐式地使用一种类型的类作为其超类型的类,但是当您开始使用值时类型,CLR将需要打包整数,以便它可以在对象的位置工作。

如果你想让它继续工作,我倾向于将声明包装在一个表达式中:

AssetDelegate aw = new AssetDelegate((m) => DelegateMethod(m));

就语法而言,我不知道这是不是很好,但请记住装箱和拆箱是很昂贵的。