为什么转换为对象时,我的C#阵列失去型标志的信息? [英] Why does my C# array lose type sign information when cast to object?

查看:123
本文介绍了为什么转换为对象时,我的C#阵列失去型标志的信息?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

调查中的错误,我发现它在C#中这种怪事是因为:

Investigating a bug, I discovered it was due to this weirdness in c#:

sbyte[] foo = new sbyte[10];
object bar = foo;
Console.WriteLine("{0} {1} {2} {3}",
        foo is sbyte[], foo is byte[], bar is sbyte[], bar is byte[]);

输出为真假真真,而我本来期望酒吧的byte [] 返回false。显然,酒吧既是字节[] 为sbyte [] ?同样的情况对于其他符号/无符号类型,如的Int32 [] VS UInt32的[] ,但不是说的Int32 [] VS 的Int64 []

The output is "True False True True", while I would have expected "bar is byte[]" to return False. Apparently bar is both a byte[] and an sbyte[]? The same happens for other signed/unsigned types like Int32[] vs UInt32[], but not for say Int32[] vs Int64[].

任何人都可以解释这种现象?这是在.NET 3.5。

Can anyone explain this behavior? This is in .NET 3.5.

推荐答案

更​​新:我已经使用这个问题作为一个博客条目,这里的基础:

UPDATE: I've used this question as the basis for a blog entry, here:

<一个href=\"http://blogs.msdn.com/ericlippert/archive/2009/09/24/why-is-covariance-of-value-typed-arrays-inconsistent.aspx\" rel=\"nofollow\">http://blogs.msdn.com/ericlippert/archive/2009/09/24/why-is-covariance-of-value-typed-arrays-inconsistent.aspx

查看博客评论对这个问题的广泛讨论。感谢伟大的问题!

See the blog comments for an extended discussion of this issue. Thanks for the great question!

您已经跨越CLI类型系统和C#类型系统之间的一个有趣的和不幸的不一致绊倒了。

You have stumbled across an interesting and unfortunate inconsistency between the CLI type system and the C# type system.

在CLI有分配兼容性的概念。如果已知数据类型S的值x是已知的数据类型T的特定存储位置Y分配兼容的,那么你可以存储中X年。如果没有,那么这样做是不是可验证code和验证将不允许它。

The CLI has the concept of "assignment compatibility". If a value x of known data type S is "assignment compatible" with a particular storage location y of known data type T, then you can store x in y. If not, then doing so is not verifiable code and the verifier will disallow it.

的CLI类型系统说,例如,该参考类型的子类型分配参考类型的超类型兼容。如果你有一个字符串,可以将其存储在对象类型的变量,因为两者都是引用类型和字符串对象的子类型。但相反的是不正确的;超类型不分配与亚型兼容。你不能坚持的东西只知道是对象转换成字符串类型的变量,而不先浇铸。

The CLI type system says, for instance, that subtypes of reference type are assignment compatible with supertypes of reference type. If you have a string, you can store it in a variable of type object, because both are reference types and string is a subtype of object. But the opposite is not true; supertypes are not assignment compatible with subtypes. You can't stick something only known to be object into a variable of type string without first casting it.

基本上转让兼容是指是有意义的这些确切数据位粘成这个变量。从源值赋值给目标变量必须是重新presentation preserving。看到我那篇文章的详细信息:

Basically "assignment compatible" means "it makes sense to stick these exact bits into this variable". The assignment from source value to target variable has to be "representation preserving". See my article on that for details:

http://ericlippert.com/2009/03 / 03 /重新presentation和身份/

之一CLI的规则是如果X是分配为Y兼容,则X []是赋值与Y []兼容。

One of the rules of the CLI is "if X is assignment compatible with Y, then X[] is assignment compatible with Y[]".

这就是数组是协变对于分配兼容性。这实际上是一个破碎的一种协方差;详情请参阅我的那篇文章。

That is, arrays are covariant with respect to assignment compatibility. This is actually a broken kind of covariance; see my article on that for details.

<一个href=\"http://blogs.msdn.com/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx\" rel=\"nofollow\">http://blogs.msdn.com/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx

这不是C#的规则。 C#的数组协变规则是如果X是引用类型隐式转换为引用类型Y,则X []隐式转换为Y []。 这是一个微妙的不同规则,因此你混乱的局面。

That is NOT a rule of C#. C#'s array covariance rule is "if X is a reference type implicitly convertible to reference type Y, then X[] is implicitly convertible to Y[]". That is a subtly different rule, and hence your confusing situation.

在CLI,UINT和INT是赋值兼容。但在C#,INT和UINT之间的转换是显式的,不含蓄,而这些是值类型,而不是引用类型。因此,在C#中,这是不合法的一个int []转换为uint []。

In the CLI, uint and int are assignment compatible. But in C#, the conversion between int and uint is EXPLICIT, not IMPLICIT, and these are value types, not reference types. So in C#, it's not legal to convert an int[] to a uint[].

但在CLI中是合法的。所以,现在我们正面临着一个选择。

But it IS legal in the CLI. So now we are faced with a choice.

1)实施是,这样,当编译器不能确定答案静态,它实际上调用它检查所有的C#规则身份 - preserving兑换的方法。这是缓慢的,和99.9%的时间相匹配什么CLR的规则。但我们采取的性能损失,以便符合C#的规则100%。

1) Implement "is" so that when the compiler cannot determine the answer statically, it actually calls a method which checks all the C# rules for identity-preserving convertibility. This is slow, and 99.9% of the time matches what the CLR rules are. But we take the performance hit so as to be 100% compliant with the rules of C#.

2)实施是,这样,当编译器不能确定答案静态,它确实令人难以置信的快速CLR分配兼容性检查,并与事实,这说,一个UINT []是一个int [],连住虽然这不会实际上是在C#中是合法的。

2) Implement "is" so that when the compiler cannot determine the answer statically, it does the incredibly fast CLR assignment compatibility check, and live with the fact that this says that a uint[] is an int[], even though that would not actually be legal in C#.

我们选择了后者。不幸的是,C#和CLI的规格不同意这个小点,但我们愿意忍受不一致。

We chose the latter. It is unfortunate that C# and the CLI specifications disagree on this minor point but we are willing to live with the inconsistency.

这篇关于为什么转换为对象时,我的C#阵列失去型标志的信息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆