Question

The question maybe a little confusing, but it's hard to make clear this question in a subject title.

I have method declared and implemented like this:

public IList<string> GetBookTitles()
{
    IList<string> bookTitles = new List<string>();
    // do something to populate the bookTitles list.
    return bookTitles;
}

Why can't I pass the result of this method to a List<string>? After all, List<string> is a kind of IList<string>.

Était-ce utile?

La solution

Well, for starters, just look at the members of IList and compare it with List. List has methods that an IList doesn't. (List has a BinarySearch method that IList doesn't, just as a single example.)

Arrays also implement IList, as an example. An array however is not a List, so you can't, and shouldn't, be able to pass a string[] to a method that accepts a List<string>.

You have a few possible solutions. One would be to just change your method to return a List<string> rather than an IList<string> (that's what I'd suggest). If that's what you really need then you shouldn't be restricting the return type to IList<string>. Another (poorer) option would be to cast the result back to a List<string> before passing it to the next method, since you happen to know that it's what the underlying type really is.

Autres conseils

After all, List<string> is a kind of IList<string>.

But there are also other kinds of IList<String>.

What if your method were to return an IList<String> which is a ReadOnlyCollection<String> instead?

IList<string> x = new ReadOnlyCollection<string>();
List<string> y = x;  //Huh?

The compiler uses the signature of your methods, not the implementation when deciding if you can assign the result of GetBookTitles to your variable, so it can't know that the result will in fact be a List. If it would allow you to do such a thing, then you could write something like this:

List<string> myBooks = GetBookTitles();
myBooks.Sort();

In your example you could do this, and in fact you can if you cast the result of your method:

List<string> myBooks = (List<string>)GetBookTitles();

But then one day you could decide that your book collection is not modifiable, and you rewrite your method as follows:

public IList<string> GetBookTitles()
    {
        IList<string> tmp = new List<string>();
        // do something to populate the bookTitles list.
        IList<string> bookTitles = new ReadOnlyCollection<string>(tmp);
        return bookTitles;
    }

ReadOnlyCollection does not implement Sort, so your app would compile, but would crash at runtime. Using the cast approach it would crash when trying to do the cast, but in this case you are taking the responsibility of deciding that that kind of cast is feasible and do not have the compiler trying to guess.

A better approach could be to use as instead of the cast and chek for null. I.e.:

List<string> myBooks = GetBookTitles() as List<string>;
if (myBooks != null)
    myBooks.Sort();

You should be able to, you just need an explicit conversion.

List<string> foo = (List<string>)GetBookTitles()

should do it.

The interface may be implemented in various classes which are not same. So, it will be difficult to find the respective class.

You can type cast from IList to List!!!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top