Arithmomaniac
Arithmomaniac

Reputation: 4794

List not inheriting an IEnumerable extension method

I have the following code that creates an extension to an IEnumerable<T>:

//http://stackoverflow.com/a/1779135/1180926
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int n)
{
  //.......
}

When I try to apply this to a list:

public static void RemoveTwo(List<string> strList)
{
    strList = strList.SkipLast(2);
}

I get the following error:

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

But List<T> inherits IEnumerable<T> (src), so shouldn't it also inherit its extension methods?

Upvotes: 2

Views: 565

Answers (3)

Douglas
Douglas

Reputation: 54877

Your issue lies not in the invocation of the extension method (which works as is), but in the assignment of its IEnumerable<string> return value to a List<string> variable. For the sake of demonstrating, the following code would work compile fine (but do nothing):

public static void RemoveTwo(List<string> strList)
{
    strList.SkipLast(2);
}

Upvotes: 2

It&#39;sNotALie.
It&#39;sNotALie.

Reputation: 22794

What you're doing wrong is assigning back to the list the IEnumerable<string> return value. You can't do that, as even though all List<T>s are also IEnumerable<T>, the reverse is not true. What you need to do is add a ToList() at the end of the SkipLast call:

public static List<string> RemoveTwo(List<string> strList)
{
    return strList.SkipLast(2).ToList();
}

Upvotes: 2

Tim Schmelter
Tim Schmelter

Reputation: 460068

You have to create a list from the IEnumerable<string>:

public static void RemoveTwo(List<string> strList)
{
    strList = strList.SkipLast(2).ToList();
}

Your extension returns IEnumerable<string> which is not a List<string>. However, if you want to modify strList you have to use methods of Lists like Remove that modify the original collection or you have to return the new list.

Instead of SkipLast you should use RemoveAt if you want to change the original collection without returning a new list.

public static void RemoveTwo(List<string> strList)
{
    if(strList.Count > 0)
        strList.RemoveAt(strList.Count-1);
    if(strList.Count > 0)
        strList.RemoveAt(strList.Count-1);
}

Upvotes: 5

Related Questions