Niraj Choubey
Niraj Choubey

Reputation: 4040

Casting issues in C#

I have aprogram

using System;
using System.Collections.Generic;

namespace Generic
{
    public class Program
    {
        public static void Main()
        {
            List<string> dd= Program.get();
        }

        public static IList<string> get()
        {
            List<string> str = new List<string>();
            return str;  
        }
    }
}

On executing above I am getting:

Cannot implicitly convert type 'System.Collections.Generic.IList<string>' to
'System.Collections.Generic.List<string>'. An explicit conversion exists (are you missing a cast?).

Since, List derives IList , this should't fail. Then why C# is throwing this error?

Upvotes: 0

Views: 358

Answers (1)

Sam
Sam

Reputation: 1206

While you can guarantee that all List objects are of type IList, you can't guarantee that all IList objects are of type List, since it could be an entirely different class that is implementing the interface. This means that in the line

List<string> dd= Program.get();

you are trying to tell the compiler that the IList is actually a List, but it doesn't know that. The IList could actually be derived from a different subclass not even related to List. You could do an explicit cast,

List<string> dd= (List<string>)Program.get();

but this could lead to runtime issues if it were ever possible for Program.get() to return something other than List which happened to implement IList.

It is much better to explicitly state the return type of get() as List<string> if you really need access to features only available in List, or to just declare the type of dd as IList<string> if the IList interface provides all of the methods you ever intend to call.

As an example, consider the following:

interface Foo {
    public void doSomething();
}

class Bar : Foo {
    public override void doSomething() {
        Console.WriteLine("Hello World!");
    }
}

class Baz : Foo {
    public override void doSomething() { 
        Console.WriteLine("Goodbye World!");
    }
}

class Program {
    public static void Main(string[] args) {
        Foo myFoo = getMyFoo();
        myFoo.doSomething();
    }

    static Random random = new Random();
    static Foo getMyFoo() {
        if (random.NextDouble() < 0.5){
            return new Bar();
        }
        else {
            return new Baz();
        }
    }
}

We can see that both Bar and Baz are of type Foo, but we are never guaranteed which type gets returned from getMyFoo(), only that it is of type Foo. We could try explicitly casting myFoo to one or the other, but we would generally fail at runtime because Baz is not of type Bar or vice versa.

Upvotes: 7

Related Questions