Lijin Durairaj
Lijin Durairaj

Reputation: 5240

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();
        }
    }

Upvotes: 2

Views: 801

Answers (2)

supercat
supercat

Reputation: 81217

An object of array type T[] has three notable abilities:

  1. Any value read from the array may be stored in a container of type T.

  2. Any value read from the array may be stored back into the same array.

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

Upvotes: 0

Eric Lippert
Eric Lippert

Reputation: 660297

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?

Upvotes: 12

Related Questions