Generics type casting - c#

I just don't get something in the .NET generic type casting.
Can someone explain what happens in the following code snippet?
void Main()
{
IEnumerable<int> ints = new List<int>();
IEnumerable<string> strings = new List<string>();
var rez1=(IEnumerable<object>)ints; //runtime error
var rez2=(IEnumerable<object>)strings; //works
var rez3=(List<object>)strings; //runtime error
}

Let's start with the second line which is easiest.
That cast works because the type parameter of IEnumerable<T> is now covariant (that's what the out in out T does). This means you can cast an IEnumerable<Derived> to an IEnumerable<Base> freely.
The first line, which would seem to be the same case, does not work because int is a value type. Interface variance does not work with value types at all because value types do not really inherit from System.Object; they can be boxed into an object, but that's not the same. The documentation mentions that
Variance applies only to reference types; if you specify a value type
for a variant type parameter, that type parameter is invariant for the
resulting constructed type.
Finally, the third line does not work because the type parameter of List<T> is invariant. You can see there is no out on its type parameter; the rules disallow that because List<T> is not an interface:
In the .NET Framework 4, variant type parameters are restricted to
generic interface and generic delegate types.

This is because interface covariance only works with reference types. Int32, of course, is a value type.
This gives more information: http://blogs.msdn.com/b/ericlippert/archive/2009/11/30/what-s-the-difference-between-covariance-and-assignment-compatibility.aspx
And so does this: http://ericlippert.com/2011/09/19/inheritance-and-representation/

The definition of every type which derives from System.ValueType, with the exception of System.Enum, actually defines two kinds of things: a heap object type, and a storage-location type. Instances of the latter may be implicitly converted to the former (making a copy of the data contained therein), and instances of the former may be explicitly typecast to the latter (likewise); even though both kinds of things are described by the same System.Type, and although they have the same members, they behave very differently.
A List<AnyClassType> will expect to hold a bunch of heap-object references; whether the list in question is a List<String>, List<StringBuilder>, List<Button>, or whatever, may be of interest to users of the list, but isn't really of interest to the List<T> itself. If one casts a List<Button> to an IEnumerable<Control>, someone who calls its GetEnumerator() method will expect to get an object which will output references to heap objects that derive from Control; the return from List<Button>.GetEnumerator() will satisfy that expectation. By contrast, if someone were to cast a List<Int32> to List<Object>, someone who called GetEnumerator() would expect something that would output heap object references, but List<Integer>.GetEnumerator will instead yield something that outputs value-type integers.
It's possible to store Int32 values into a List<Object> or a List<ValueType>; storing an integer to such a list will convert it to its heap object form and store a reference to it; calling GetEnumerator() would yield something that outputs heap references. There is no way to specify, however, that such a list will only contain instances of the heap type corresponding to Int32. In C++/CLI, it's possible to declare variables of type "reference to heap-stored valuetype", but the mechanisms behind generic types in .net cannot work with such types.

Related

cast objects to a known interface with generic type parameter where that type parameter is given as type variable at runtime

I am doing some reflection stuff. I have the following situation:
I have a variable Type myType with some runtime value (e.g. string or List<int>).
I have two variables object a and object b for which I know that they are of type IImmutableSet<myType>. (So if myType=string they'd be IImmutableSet<string>, if myType=List<int> they'd be IImmutableSet<List<int>> and so on.)
How can I cast them?
Motivation:
I want to do a comparison of a and b by content, i,e.
check that both their size is equal. For that, I need a Count property (or equivalent property/method).
check that a contains all elements of b. For that, I need a Contains(...) method.
If I had ISet<T>s, I'd just cast them to ICollection and use that interface's Count and Contains(...).
But since IImmutableSet<T> does not implement any non-generic collection interface, I need to cast a and b to IImmutableSet<myType> (or IReadOnlyCollection<myType>). That syntax doesn't work because it expects a compile-time constant type.
--
Another thought... if casting isn't possible, I'd be happy with being able to call the said methods. Since I'm already doing heavy reflection, I don't care about speed.

Why is Array Covariance not safe?

i was reading about the covariance & contravariance from this blog and the
covariance on Array got me confused
now, if i have this
object[] obj= new string[5];
obj[0]=4;
why am i getting error during run time? Theoretically obj is a variable of type Object and Object can store any type, as all the types are inherited from the Object class. Now when i run this code i am not getting any run time error, can anyone explain me why
class baseclass
{
}
class client
{
static void Main()
{
object obj = new baseclass();
obj = 4;
Console.Read();
}
}
It is in fact confusing.
When you say object[] objs = new string[4] {}; then objs is actually an array of strings. Unsafe array covariance is unsafe because the type system is lying to you. That's why it is unsafe. You think that your array can hold a boxed integer, but it is really an array of strings and it cannot actually hold anything but strings.
Your question is "why is this not safe", and then you give an example of why it is not safe. It is not safe because it crashes at runtime when you do something that looks like it should be safe. It's a violation of the most basic rule of the type system: that a variable actually contains a value of the type of the variable.
For a variable of type object, that's not a lie. You can store any object in that variable, so it's safe. But a variable of type object[] is a lie. You can store things in that variable that are not object[].
This is in my opinion the worst feature of C# and the CLR. C# has this feature because the CLR has it. The CLR has it because Java has it, and the CLR designers wanted to be able to implement Java-like languages in the CLR. I do not know why Java has it; it's a terrible idea and they should not have done it.
Is that now clear?
An object of array type T[] has three notable abilities:
Any value read from the array may be stored in a container of type T.
Any value read from the array may be stored back into the same array.
Any value that fits in a container of type T may be stored into the array.
A non-null reference of type T[] will be capable of holding a reference to any object of type U[], where U derives from T. For any possible type U derived from T, any value read from a U[] may be stored into a container of type T, and may also be stored back into the same array. If a container of type T holds an reference to an object which is derived from T, but is not of type U nor any type derived from U, then a U[] would be incapable of holding that reference.
It would be awkward to allow code to read an item from one array and write it back to the same array, without also allowing it to ask for an item be read from one array and written into another. Rather than trying to limit such operations via compile-time constraints, C# opts instead to say that if code tries to store a value held in a T into an array identified via T[], such an operation will succeed if the T is null or identifies an object of a type not derived from the element type of the actual array identified by the T[].

How do generics implement structs?

I was thinking about this. classes are obviously passed around by ptr. I suspect structs are passed around by copying it but i don't know for sure. (it seems like a waste for an int array to have every element a ptr. and passing ptrs for ints)
But thinking about it, List<MyStruct> can not know the size of my struct. What happens when i do this? Are there multiple copies of "List`1" and every time i use it with a storage size it does not have it creates a new implementation? (adjusting for the new offsets of T and such).
That could make sense since the source would be in the CIL inside of a DLL. But i am completely guessing, how is it done? Perhaps a reference or page # to the ECMA standards?
Generics use the concept of open and closed generic types: A parametrized generic class definition (i.e. List<T>) is an open generic type of which the runtime generates a closed generic type for each different use you have in your code, i.e. a different type is created for List<int> and for List<MyStruct> - for each closed generic type the size and type of T is known at run-time.
Clarification from MSDN:
When a generic type or method is
compiled into Microsoft intermediate
language (MSIL), it contains metadata
that identifies it as having type
parameters. How the MSIL for a generic
type is used differs based on whether
the supplied type parameter is a value
type or reference type.
When a generic type is first
constructed with a value type as a
parameter, the runtime creates a
specialized generic type with the
supplied parameter or parameters
substituted in the appropriate
locations in the MSIL. Specialized
generic types are created one time for
each unique value type that is used as
a parameter.
Generics work somewhat differently for
reference types. The first time a
generic type is constructed with any
reference type, the runtime creates a
specialized generic type with object
references substituted for the
parameters in the MSIL. Then, every
time that a constructed type is
instantiated with a reference type as
its parameter, regardless of what type
it is, the runtime reuses the
previously created specialized version
of the generic type. This is possible
because all references are the same
size.
The CLR compiles 1 version of the generic class and uses it for all reference types. It also compiles 1 version for every value type usage to optimize for performance.

c# - where do arrays inherit from (i.e .int[] )

When creating an array, such as int[], does this inherit from anything? I thought it might inherit from System.Array, but after looking at the compiled CIL it does't appear so.
I thought it might inherit from System.Array or somehting similair, considering you can call methods and access properties on an array.
I.e.
int[] arr = {1, 2};
arr.Initialize();
arr.Length;
All arrays derive from System.Array. From an (admittedly ancient) edition of MSDN magazine:
All array types are implicitly derived from System.Array, which itself is derived from System.Object. This means that all arrays are always reference types which are allocated on the managed heap, and your app's variable contains a reference to the array and not the array itself.
From section 19.1.1 of the C# Language Specification (emphasis mine):
The type System.Array is the abstract base type of all array types. An implicit reference conversion
(§13.1.4) exists from any array type to System.Array and to any interface type implemented by
System.Array. An explicit reference conversion (§13.2.3) exists from System.Array and any interface
type implemented by System.Array to any array type. System.Array is not itself an array-type. Rather,
it is a class-type from which all array-types are derived.
An array does inherit from System.Array. It's a specialisation of a generic type, kind of like System.Array<int>, except that the runtime treats arrays as "special" - they are a special case of generics that existed in .NET 1.0 before the "general" generics were introduced in .NET 2.0.
Edit: Just checked my answer using Reflection and it looks like the base type of an array actually is System.Array. Corrected.
One thing I found interesting is that arrays also implements ICollection<>
int[] foo = new int[]{ };
ICollection<int> bar = foo;
// So, arrays would have type infered to use ICollection<> overload
IEnumerable<T> Foo<T>(Func<IEnumerable<T>> bar); // .Count()
ICollection<T> Foo<T>(Func<ICollection<T>> bar); // .Count

System.ValueType Understanding

I tried to create a ValueType.
I understand that creating a struct would help me.
I also tried to derive a type from System.ValueType which is an abstract class.
But I got a compiler error message
".. cannot derive from special class System.ValueType"
When I see the metadata of ValueType, it looks to be a regular abstract class. Any non sealed class should be derivable. But System.ValueType is not a sealed class.
What made it special?
Is it the C# compiler that senses it as special?
If so, is it recommended as a rule for compiler design? I mean is it part of Common Language Specification?
ValueType is a little white lie.
The built-in numeric types (int, long, byte), char, enums and structs are all value types.
This means that they have a different concepts of identity and equivalence to object types. If I do x = y and x and y are reference types, then x and y now point to precisely the same object. However, if I do x = y and x and y are value types, then x and y are now two completely different objects that happen to be identical. (This is also reflected in == and Equals, though that can be overridden).
(This is where people get sidetracked by talking about the stack and the heap, if they haven't already, really that's an implementation detail and while important, is not the point of the distinction between value and reference types).
Now, mostly this is all and good but one thing about reference types is that they all benefit from inheriting from System.Object. The value type int doesn't really, and that's good too as it's much better in many ways that it just be four bytes of memory handled by the lovely CPU instructions that are so good at doing so. Still, it's sometimes useful to be able to treat an int as if it also inherited from System.Object, and so you can.
Of course, this means that you may do things with int that only make sense to do on a System.Object, so when you do so the int is "boxed" and can then be "unboxed" again.
This is great, but what if we wanted to do something specific to value types? More to the point, what if the designers of the CLR did (in particular, they wanted a GetHashCode for value types that related to the value-based equivalence descibed above, rather than the identity-based equivalence that objects have)?
For this purpose we have ValueType. The system treats all value types as inheriting from this class, which in turn inherits from Object. Enum in turn inherits from value type and all enum types inherit from it, allowing some common functionality across all enums.
So, if you ever want to treat a superclass of all value types, use ValueType, but if you want to actually create a value type, create a struct or an enum as appropriate.
The Common Type System explanation:
A structure is a value type that derives implicitly from System.ValueType, which in turn is derived from System.Object. A structure is very useful for representing values whose memory requirements are small, and for passing values as by-value parameters to methods that have strongly typed parameters. In the .NET Framework class library, all primitive data types (Boolean, Byte, Char, DateTime, Decimal, Double, Int16, Int32, Int64, SByte, Single, UInt16, UInt32, and UInt64) are defined as structures.
Like classes, structures define both data (the fields of the structure) and the operations that can be performed on that data (the methods of the structure). This means that you can call methods on structures, including the virtual methods defined on the System.Object and System.ValueType classes, and any methods defined on the value type itself. In other words, structures can have fields, properties, and events, as well as static and nonstatic methods. You can create instances of structures, pass them as parameters, store them as local variables, or store them in a field of another value type or reference type. Structures can also implement interfaces.
Value types also differ from classes in several respects. First, although they implicitly inherit from System.ValueType, they cannot directly inherit from any type. Similarly, all value types are sealed, which means that no other type can be derived from them. They also do not require constructors.
For each value type, the common language runtime supplies a corresponding boxed type, which is a class that has the same state and behavior as the value type. An instance of a value type is boxed when it is passed to a method that accepts a parameter of type System.Object. It is unboxed (that is, converted from an instance of a class back to an instance of a value type) when control returns from a method call that accepts a value type as a by-reference parameter. Some languages require that you use special syntax when the boxed type is required; others automatically use the boxed type when it is needed. When you define a value type, you are defining both the boxed and the unboxed type.
The strangeness of ValueType is to allow the above to happen.
Structures are value types. Value types are special because they are allocated on the stack rather than the heap. To "inherit" from ValueType, you must create a struct.
Not being able to derive from ValueType is specific to the C# compiler. If we look at managed C++ code:
value class Foo {};
value class Foo : System::ValueType {};
Both of these compile and are identical. Of course,
ref class Foo : System::ValueType {};
Will give error C3050: a ref class cannot inherit from 'System::ValueType'.
Not sure what other compilers allow.
If you want to derive from ValueType in C#, use struct and not class, and the compiler takes care of it.
C# does not allow value types to inherit from other classes. Value types (struct) can implement interfaces.
you cannot subclass ValueType directly. All value types derives from ValueType implicitly. Unlike with reference types, you cannot derive a new type from a value type. However, like reference types, structs can implement interfaces.
see MSDN to know more
A 'class' extends 'System.Object', a 'struct' extends 'System.ValueType'. If you could make a class extend 'System.ValueType', then there wouldn't be much point to the 'struct' keyword.
Yes
Yes. There should only be one way to accomplish any given thing. As soon as two methods of doing something are provided, you've just make everything more complicated. General rule.
This is what perplexes me... Enum is derived from ValueType. Which makes me think the above is just a compiler restriction.
[Serializable, ComVisible(true)]
public abstract class Enum : ValueType, IComparable, IFormattable, IConvertible
{
...
}

Categories