2

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?

Arithmomaniac
  • 4,604
  • 3
  • 38
  • 58

3 Answers3

5

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);
}
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
2

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);
}
Douglas
  • 53,759
  • 13
  • 140
  • 188
2

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();
}
It'sNotALie.
  • 22,289
  • 12
  • 68
  • 103
  • You got tripped up by New-Memberese again :). Your code does nothing to the original list, to make your code work you would need to pass strList in by `ref`. – Scott Chamberlain Jul 01 '13 at 22:52
  • Yes, you are re-assinging it back to the local variable `strList`, however the list that was passed in to the `RemoveTwo` function will not be modifed. You either need to pass the list in as a `ref` so the original list will be updated when you re-assign it or return the new list you generated as a return value. – Scott Chamberlain Jul 01 '13 at 22:55