7

谁能阐明为什么逆变不适用于 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;
}
4

2 回答 2

5

问题是int 不是 object

一个 int 可以装箱到一个对象。生成的对象(又名 boxed int)当然是一个对象,但它不再完全是一个 int。

请注意,我在上面使用的“ is ”与 C# 运算符is不同。我的“”的意思是“可以通过隐式引用转换”。这就是我们谈论协变和逆变时使用的“是”的含义。

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

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

考虑下面的例子。两个变量houseasset引用同一个对象。另一方面,变量integer和持有相同的值,但它们引用不同的东西。boxedInt

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

int integer = 42;
object boxedInt = integer;

装箱和拆箱并不像看起来那么简单。它有许多微妙之处,并且可能会以意想不到的方式影响您的代码。将拳击与协变和逆变相结合是一种让任何人眼花缭乱的简单方法。

于 2010-06-11T03:26:23.670 回答
1

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

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

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

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

于 2010-06-09T22:14:08.130 回答