Within the .net runtime, each type of non-NULL value has an associated reference type (often called a "boxed field type") that derives from System.ValueType . Saying Object Foo = 5; will not actually store Int32 in Foo ; instead, it will create a new instance of the reference type associated with Int32 and save the reference to that instance. The class constraint for a generic type indicates that the type in question should be a kind of reference type, but by itself excludes the possibility that this type can be used to pass a reference to an instance of the type with a short value. In most contexts, outside of general type constraints, interface types are treated as class types.
It is important to note that not only box-type value types are stored as reference types; they behave like reference types. For example, List<string>.Enumerator is a value type that implements IEnumerator<string> . If one has two variables of type List<string>.Enumerator , copying one to the other will copy the state of the enumeration, so there will be two independent and independent enumerations that point to the same list. Copying one of these variables to a variable of type IEnumerator<string> will create a new instance of the boxed value type associated with List<string.Enumerator and save the link to this new object (which will be the third independent enumerator) in the last variable. However, copying this variable to another type of IEnumerator<string> simply save the reference to the existing object (since IEnumerator<string> is a reference type).
The C # language tries to pretend that value types come from Object , but within the .net Runtime kinetics they really don't. Instead, they are convertible to types that are inferred from System.ValueType (which, in turn, comes from Object ). The latter types satisfy type restrictions, although the former will not. By the way, despite its name, System.ValueType is actually a class type.
source share