Why is Array Covariance not safe? - c#

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[].

Related

Common Type System - Structures

i am stuck in programming terminology here, which is getting me confused and i cannot gather my thoughts on how to actually and correctly express(write) these few MSDN theory sentences from the Common Type System page.
Would anyone help me on this one, i want to understand this!
And if someone would be so kind to write some code and comment on this issue,
it would be awesome and praiseworthy of you!
//This is the text(it is taken from the "Structures" paragraph):
https://msdn.microsoft.com/en-us/library/zcx1eb1e(v=vs.110).aspx#
"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."
Thank You in advance, best regards!
An object and a value type are stored differently. An object is a pointer to memory in the heap which contains the binary representation of that object. The stack is memory allocated to store pointers and value types. So a function doesn't have a pointer to an integer or bool. It is passed a copy of the actual value.
But if you have a method like this:
string GetString(object o)
{
return o.ToString();
}
That method expects an object, a pointer to a location in memory, even if you pass a value type to it. So in order to do that, the framework has to create an object stored on the heap containing that int so that it can pass a reference (pointer) to that value to the function. That's boxing.
Boxing is implicit. You don't have to call some conversion function to convert an int to an object.
Unboxing occurs when you take that object and cast it as a value type. For example,
object x = 5; //Boxes the value to create an object with a pointer
var y = (int)x; //Unboxes the value, creating an int on the stack.
When you unbox the object stored in the heap and referenced by x is inspected and its value retrieved. Unboxing is explicit. When you convert anything from object to a value type you must specify the type to which you are converting it.
.NET is language agnostic which allows programmers to write code in different languages (which can be compiled to IL), and that code can interact with other code written in different languages.
This feature is provided by the CTS (Common Type System), a standard that specifies how type definitions are represented in the memory and how types are declared, used, and managed in the CLR (Common Language Runtime).
Example
C# has an int data type and VB.NET has a Integer data type. After the compilation, both instances of int and Integer will use the same structure Int32 from CTS.

Object Class Primitive Types Stack and Heap

First of all I apologize if it sounds too dumb. but I always find myself asking the following questions.
Since object class is the ultimate base class for all classes in .Net and class is a reference type, reference types are stored on heap so how did anything even get to the stack.
I know primitive types get stored on stack and that's where I get confused.
Take int32 for instance, if its a class and its base class is object, then its a reference type, should be on heap. How does it go to stack.
If its not a class then how can we do this
int i = 1;
object obj = i;
Since I cannot do something like
int i = 1;
MyClass myObj = i;
Edit
From the answers I got, int is struct rather than class. Still the confusion is how a value type's base class is a reference type (object) and its a value type not a reference type.
Another point that came up is that "value-types that belong to a class do not get stored on the stack", I guess everything is inside a class, even the Main method inside a console Program. For me that means all the variable somehow belong to a class? So How do they go to stack?
First of all I apologize if it sounds too dumb. but I always find myself asking the following questions.
These are very common questions.
Since object class is the ultimate base class for all classes in .Net and class is a reference type, reference types are stored on heap so how did anything even get to the stack.
You are confusing many things. Let's start with:
An instance of a value type is a value.
A reference is a value.
A reference refers to an instance of a reference type. (Or it is null, in which case it refers to nothing.)
OK, so now we know that there are three kinds of things, and two of them are values.
So now let's state your sentence correctly:
The object class is the ultimate base class for all classes in .NET. All instances of classes are instances of reference types. All instances of reference types are stored on heap. How is anything stored on the stack?
Now that we have the question phrased correctly the answer is clear. References and instances of value type can go on the stack.
Let's move on.
I know primitive types get stored on stack and that's where I get confused.
Banish the word "primitive type" from your vocabulary; it is meaningless. Let's rephrase:
I know that instances of value types get stored on stack
No, you do not know that because in order to count as knowledge a statement must be true. That statement is false. Values get stored in variables. Variables are either long-lived or short-lived. Short-lived variables go on the stack. Long-lived variables go on the heap.
Take int32 for instance, if its a class and its base class is object, then its a reference type, should be on heap.
Int32 is not a class. It's a struct. It is not a reference type.
Still the confusion is how a value type's base class is a reference type (object) and its a value type not a reference type.
Mary is a mother. She is female. Are all her children therefore also female?
How does it go to stack.
An integer goes on the stack when the integer is stored in a short-lived variable.
A reference goes on the stack when the reference is stored in a short-lived variable.
Whether a value is a reference or an instance of value type is irrelevant; what matters is how long does the variable live?
If its not a class then how can we do this
int i = 1;
object obj = i;
Good question. A special class is generated. Think of this as being:
class BoxedInt
{
int value;
public BoxedInt(int v) { this.value = v; }
public int Unbox() { return this.value; }
}
So then your program fragment is:
int i = 1;
object obj = new BoxedInt(i);
And then
int j = (int)obj;
is the same as
int j = ((BoxedInt)obj).Unbox();
Another point that came up is that "value-types that belong to a class do not get stored on the stack
A better way to say that is: fields of a reference type are long-lived variables. Therefore they are stored on the heap.
I guess everything is inside a class, even the Main method inside a console Program.
Yes, all code is inside a class or struct.
For me that means all the variable somehow belong to a class?
No, a local variable is not a member of a class.
I live in a yellow house. Are all the objects inside of it also therefore yellow?
So How do they go to stack?
A local variable in an ordinary method is short-lived, so it goes on the stack.
Simply stop thinking about the stack as having something to do with what kind of data is being stored. The stack has nothing whatsoever to do with what kind of data is being stored. Think about variables. The stack is the place for short-lived variables. The heap is the place for long-lived variables. The type of the variable is irrelevant.
Int32 is a ValueType and hence it would be allocated in stack. The keyword int refers to the struct System.Int32.
Types in .net are separated into value types and reference types.
Value types are either stack-allocated or allocated inline in a structure.
Reference types are heap-allocated.
Value types consist of two main categories:
Structs{bool,Numeric,custom}
Enumerations
Both reference and value types are derived from the ultimate base class Object.
In cases where it is necessary for a value type to behave like an
object, a wrapper that makes the value type look like a reference
object is allocated on the heap, and the value type's value is copied
into it. The wrapper is marked so the system knows that it contains a
value type. This process is known as boxing, and the reverse process
is known as unboxing.
Refer here
Int32 is not a class.It is a struct.And structs are specially handled by the compiler.
object obj = i;
This is called boxing. Because all of the classes are implicitly inherits from object, you can assign anything to object.You should take a look at the documentation for this and also there are thousands of articles about boxing and unboxing on the Internet.
From MSDN:
Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type. When the CLR boxes a value type, it wraps the value inside a System.Object and stores it on the managed heap.
Here are some references that might be useful
struct (C# Reference)
Types (C# Reference)
Value Types and Reference Types
Boxing and Unboxing
The Truth About Value Types - Eric Lippert
- Related Questions
Reference and Value types scenario
What is the difference between a reference type and value type in c#?
Short answer:
The type System.Object is not a "class" but instances of type System.Object are reference types.
When type B inherits from type A, the only thing that is implied is that B gets all of A's public or protected non-static methods, properties, and events.
Classes are references types and are always allocated on the heap.
Structs are value types and may be allocated on the stack, heap, or CPU registers.
Basically, value types can have two different representations in memory (boxed and non-boxed) while reference types only have one kind of representation in memory.
Longer Answer:
First of all, you can absolutely do this:
int i = 1;
MyClass myObj = i;
Just define MyClass as:
class MyClass
{
int i;
public MyClass(int i)
{
this.i = i;
}
public static implicit operator MyClass(int i)
{
return new MyClass(i);
}
}
(Note well that in this example, the field, i, of the class MyClass is heap-allocated even though it is a value type)
Secondly, value types are not necessarily stored on the stack as in the following cases:
Value-typed fields that belong to a class
Closed over local value-type variables (i.e. variables captured by a closure)
Now, when type B inherits from type A, that means only that B gets all of A's properties, methods, and events. It does not prescribe how instances of B should be allocated.
Primitive data types are value type, their size is defined at compile time, so compiler push them on stack for faster access, while reference type are just pointers to starting address of object stored on heap and it's memory is not assigned on compile time(assigned on runtime).
you cannot do
int i = null; // Because it's value type and need some value
(Default is 0) here int is alias to Int32 which is structure and
structure is value type and same is for other primitives

Unable to understand how boxing is done

I was studying boxing and unboxing.
I went through this example, I am unable to understand the answer.
Can anyone explain to me please.
I know what boxing and unboxing does now, by looking at a simple example, but this example, confuses a bit.
An example of boxing and then unboxing, a tricky example.
[struct|class] Point {
public int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
Point p = new Point(1, 1);
object o = p; p.x = 2;
Console.WriteLine(((Point)o).x);
I read the answer as:
It depends! If Point is a struct then the output is 1 but if Point is a class then the output is 2! A boxing conversion makes a copy of the value being boxed explaining the difference in behavior.
Here is ((point)o).x a boxing or unboxing?
Didn't understand, can anyone explain to me please.
I know that the answer should come 1, but if class then how 2?
I don't know why everyone is writing an essay, it's pretty simple to explain:
When you cast a struct into object, it is copied into a new object.
When you cast an object into a struct, it is copied into a new struct.
When you cast between classes, the object's contents are not copied; only the reference is copied.
Hope that helps.
Although C# tries to pretend that structure types derive from Object, that's only half true. According to the CLI spec, a structure type specification actually defines two kinds of thing: a type of heap object which derives from System.ValueType (and in turn System.Object), and a kind of storage location (local variable, static variable, class field, struct field, parameter, or array slot) which does not derive from anything, but is implicitly convertible to the heap object type.
Every heap object instance contains all the fields defined by the type or its parent classes (if any), along with a header which identifies its type and some other information about the instance. Every struct-type storage location contains either the bytes necessary to hold its value (if a primitive type), or else holds the concatenated values of all its fields; in neither case does it contain any sort of header that identifies its type. Instead, value types rely upon information in the generated code to know what they are.
If one stores a value type to a storage location of that value type, the compiler will overwrite all the bytes occupied by the destination with values taken from the original value type. If, however, one tries to store a value type to a reference-type storage location (like Object), the runtime will generate a new heap object with enough space to hold all the data from the value type, along with a header identifying its type, and store in the destination location a reference to that new object. If one tries to typecast a reference type to a value type, the runtime will first verify that the object is of the proper type and, if so, copy the data from the heap object to the destination.
There are a couple of tricky scenarios involving interfaces and generics. Interface types are reference types, but if a struct implements an interface, the implementing methods may act directly upon a boxed struct instance without having to unbox and rebox it. Further, interface types used as generic constraints do not require boxing. If one passes a variable of a value type like List<int>.Enumerator to a function EnumerateThings<TEnumerator>(ref TEnumerator it) where TEnumerator: IEnumerator<int>, that method will be able to accept a reference to that variable without boxing.
Since Point is Struct and Structs are value types which means they are copied when they are passed around.
So if you change a copy you are changing only that copy, not the original.
However if Point was a class, then it was passed by reference.
So if you change a copy you are changing only that copy and also the original.
As for your confusion
object o = p; is boxing
whereas
(Point)o is unboxing
To understand boxing you need to understand the difference between Value types and Reference types.
I think the simplest way to understand it is:
"Value types are allocated in-line. Reference types are always
allocated on the Heap"
meaning, that if you add a value type (struct, int, float, bool) inside of a reference-type as a class variable (public or private), that value-type's data is embedded wherever that reference-type lives on the Heap.
If you create a value-type inside of a function, but do NOT assign it to a public/private variable, that value-type is allocated in the Function-Stack (meaning once you leave that function it will get collected)
So, given that background knowledge, it should be pretty self-explanatory what happens when you "box" a value-type: you have to take that value type (wherever it was in-line allocated) and turn it into a reference-type (create a new object for it on the Heap).
First you need to know where objects are stored. Structs, enums and other value types are stored on the stack, in registers, or on the heap; classes and other reference types are stored on the heap. A good tutorial is here.
Boxing is done when a value type is being stored in a heap. A copy is being made from stack to heap. Unboxing is the other way around, a copy of a value will be made from heap to stack.
1 Point p = new Point(1, 1);
2 object o = p;
3 p.x = 2;
4 Console.WriteLine(((Point)o).x);
In your code above, if Point is a struct, a copy will be made to object "o". On your line 3, what you modified is is the Point in stack. On the last line you unboxed the object "o" but the value you will get is the copied value from the heap.
If the Point is class, in line 1, a space is created for the Point in the heap. Line 2, creates a new variable "o" that references to the same memory space. Remember that "p" & "o" are referencing on the same memory address location, so if you modify any of the variable just like in line 3, you will get the modified value on both variable.

Generics type casting

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.

At what level does boxing of an object occur in .net?

If I have an object such as List<string> that I cast into an object, and then back again, will all the strings get cast as well or just the list that contains them?
I'm thinking that the compiler would only have to check if the object was of type List<string> before casting back into a List<string> but I grew up in C#, so I'm not entirely certain what goes on behind the code that I write.
When you cast a List<string> to an object, you're not really doing any casting at all. You're assigning one reference to some data, to a less-specific reference. The string objects that it contains aren't changed at all, either.
Also, to clarify, there is no boxing involved in this case. Boxing occurs when you create a reference to a value type like an int or some struct, by assigning it or passing it somehow to a variable of type object.
Boxing occurs when a struct / value type is stored in a location which is typed to object or an interface which that struct implements. In this scenario both List<string> and string are reference types so no boxing occurs.
struct S1 : IComparable {
...
}
S1 local = new S1(); // No box.
object obj = local; // Box S1 instance into object
IComparable comp = local; // Box S1 instance into IComparable
obj = "hello"; // String is a reference type, no boxing
string is a reference type - an instance of string will never get boxed.
If however you had a List<int>, the List is a reference type, so there will be no boxing here either. int is a value type and it could be boxed IF it were cast to an object (either implicitly or explicitly).
Boxing only affects value types - List<T> is a class, hence a reference type, changing the generic type T does not affect whether an instance is passed by value or by reference.
Generic collections help prevent boxing as it enables value types to be read / written without being boxed to an object.
For every value type, there is a corresponding object type with the same name which is derived from ValueType. Whenever it is necessary to create a storage location (field, variable, or parameter) of a given type, the system will allocate space to store either a heap reference (if the type does not derive from ValueType), all of the type's fields (if it's a 'struct'), or the bits holding the types value. Boxing occurs when an attempt is made to store an instance of a value type into a heap reference. Unboxing occurs when an attempt is made to use a heap reference as though it were a value type. Note that in some contexts, unboxing will copy the contents of boxed object to a new storage location, but in other contexts it will regard the boxed instance as a storage location. The semantics of this are not always clear, which is one of the reasons some people hate mutable structs. In practice, mutable structs are fine if one avoids usage scenarios where the semantics get murky, and even immutable structs can suffer from the same murky semantics.
Boxing and Unboxing is the actions that applies to Value Types not to Reference Types.
It's not that, it's just a simple cast.
Only the List<string> will be casted.
If you want to cast the List<string> items do this:
List<string> list = new List<string>{"first", "second"};
List<object> objectsList = list.Cast<object>();
P.S. string is a reference type so it can't really get boxed and unboxed

Categories