逆变委托值类型
谁能解释一下为什么逆变不适用于 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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题在于int 不是对象。
int 可以装箱到一个对象。当然,结果对象(又名装箱 int)是一个对象,但它不再是一个 int 了。
请注意,我上面使用的“is”与 C# 运算符 是。我的“是”意思是“可以通过隐式引用转换进行转换”。这就是我们谈论协变和逆变时使用的“is”的含义。
int 可以隐式转换为对象,但这不是引用转换。它必须装箱。
House
可以通过引用转换隐式转换为Asset
。无需创建或修改任何对象。考虑下面的例子。变量
house
和asset
都引用同一个对象。另一方面,变量integer
和boxedInt
拥有相同的值,但它们引用不同的东西。装箱和拆箱并不像看起来那么简单。它有许多微妙之处,可能会以意想不到的方式影响您的代码。将拳击与协变和逆变混合在一起是一种让任何人眼花缭乱的简单方法。
The problem is that an int is not an object.
An int can be boxed to an object. The resulting object (aka boxed int) is, of course, an object, but it's not exactly an int anymore.
Note that the "is" I'm using above is not the same as the C# operator is. My "is" means "is convertible to by implicit reference conversion". This is the meaning of "is" used when we talk about covariance and contravariance.
An int is implicit convertible to an object, but this is not a reference conversion. It has to be boxed.
An
House
is implicit convertible to anAsset
through a reference conversion. There's no need to create or modify any objects.Consider the example below. Both variables
house
andasset
are referencing the very same object. The variablesinteger
andboxedInt
, on the other hand, hold the same value, but they reference different things.Boxing and Unboxing is not as simple as it may look like. It has many subtleties, and might affect your code in unexpected ways. Mixing boxing with covariance and contravariance is an easy way to make anyone dazzle.
我同意 Anthony Pegram 的评论 - 它基于与值类型相比具有不同内存占用的引用类型:CLR 可以隐式使用一种类型的类作为其超类型的类,但是当您开始使用值类型时, CLR 需要对整数进行装箱,以便它可以在对象的位置工作。
如果你想让它工作,我倾向于将声明包装在一个表达式中:
我不知道这是否是一个好的做法,就语法而言,但请记住,装箱和拆箱是昂贵的。
I agree with Anthony Pegram's comment - it is based on reference types having a different memory footprint than the value types: the CLR can implicitly use a class of one type as a class of its super type, but when you start using value types, the CLR will need to box your integer so it can work in the place of the object.
If you're looking to make it work anyway, I have a tendency to wrap the declaration in an expression:
I don't know if that's good practice or not as far as syntax goes, but remember that boxing and unboxing is expensive.