开发者

CLR specification on boxing

开发者 https://www.devze.com 2023-04-11 10:30 出处:网络
I\'m currently reading the CLR specification. I have a bit of trouble understanding section \"I 8.2.4 Boxing and unboxing of values\".

I'm currently reading the CLR specification. I have a bit of trouble understanding section "I 8.2.4 Boxing and unboxing of values".

1. When can boxed types be used?

On the one hand it states:

For every value type, the CTS defines a corresponding reference type called the boxed type. [...]开发者_如何转开发 The representation of a value of a boxed type (a boxed value) is a location where a value of the value type can be stored. A boxed type is an object type and a boxed value is an object.

A boxed type cannot be directly referred to by name, therefore no field or local variable can be given a boxed type. The closest named base class to a boxed enumerated value type is System.Enum; for all other value types it is System.ValueType. Fields typed System.ValueType can only contain the null value or an instance of a boxed value type. Locals typed System.Enum can only contain the null value or an instance of a boxed enumeration type.

Does this mean I can have properties/methods which use strongly typed boxed value types, or is this just an omission in the spec? If so, why can I have properties but not fields?

On the other hand C++/CLI seems to support boxed value types even in local variables using MyStruct^ but seems to behave strangely with boxed primitive types(System.Int32^). But I'm not sure which part of that is C++/CLI compiler magic (it might use tagged Object variables instead), and which part is handles by the CLR.

The spec further states:

CLS Rule 3: Boxed value types are not CLS-compliant. [Note: In lieu of boxed types, use System.Object, System.ValueType, or System.Enum, as appropriate.

This seems to imply that strongly typed boxed value types can be part of the public interface of a type. But should not be used for CLS compliance(which is understandable since most languages don't support them).

So where can strongly typed boxed value type be used? And why can it be used in those places, but not others?

2. Boxing reference types

The spec also mentions boxing reference types:

A type is boxable if it is one of the following:

[...]

  • A reference type (including classes, arrays, delegates, and instantiations of generic classes) excluding managed pointers/byrefs (§8.2.1.1)

  • A generic parameter (to a generic type definition, or a generic method definition) [Note: Boxing and unboxing of generic arguments adds performance overhead to a CLI implementation. The constrained. prefix can improve performance during virtual dispatch to a method defined by a value type, by avoiding boxing the value type. end note]

Is boxing a reference type a no-op? Allowing boxing reference types is useful on generic parameters where you don't know if something is a value or reference type. So I assume boxing a reference type is allowed for consistency with generic parameters that represent a reference type.

3. What is the meaning of an interface being "defined on a type"?

And finally I have problems understanding the following paragraph:

Interfaces and inheritance are defined only on reference types. Thus, while a value type definition (§8.9.7) can specify both interfaces that shall be implemented by the value type and the class (System.ValueType or System.Enum) from which it inherits, these apply only to boxed values.

What is the meaning of an interface being "defined on a type"? My understanding is that casting to interfaces/base classes boxes the value, but you can still call methods defined in such an interface/class on the unboxed using constrained virtual calls. (virtcall with constraint prefix)


Yes, the C++/CLI language allows declaring strongly typed boxed value types:

public ref class Class1
{
public:
    int^ boxedInt;
    Class1() { boxedInt = 42; }
};

It observes the CLI spec however, the boxedInt field is typed ValueType in the metadata. It remembers, and checks, the boxed type with modOpt attributes:

field boxedInt: public class System.ValueType modopt(System.Int32) modopt(System.Runtime.CompilerServices.IsBoxed)

The exact same thing is possible in C#, minus the compiler checking that only int values are assigned to the field. Simply declare the field as ValueType. This has otherwise no practical value.

0

精彩评论

暂无评论...
验证码 换一张
取 消