2

.NET Framework 4.7.2. Visual Studio 2019. This issue is not specifically addressed in other posts about this error.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Stuff
{
    class Program
    {
        static void Main(string[] args)
        {
         string firstPart = "ABC 123 XYZ";
         string firstPartMinusLast = string.Join(" ", firstPart.Split(' ').SkipLast(1));
         Console.WriteLine(firstPartMinusLast);
        }
    }
}

I get an Intellisense error on SkipLast:

string[] does not contain a definition for 'SkipLast' and no accessible extension method 'SkipLast' accepting a first argument of type 'string[]' could be found (are you missing a using directive or an assembly reference?)

Per any documentation I can find online, using System.Linq is supposed to cover this method?

Stpete111
  • 3,109
  • 4
  • 34
  • 74
  • 5
    `SkipLast()` is part of .NET Core, but not .NET Framework. – itsme86 Aug 20 '20 at 19:47
  • 5
    [SkipLast](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.skiplast) seems to be new in NetStandard 2.1. It didn't exists in Net Framework 4.7. – Justin Lessard Aug 20 '20 at 19:47
  • @Sach SkipLast is a method of `System.Collections.Generic.IEnumerable` and Arrays implements that interface – Justin Lessard Aug 20 '20 at 19:48
  • Ahhh I see. So to achieve `SkipLast` in .NET Framework, will I need to do some sort of calculation on count of strings generated by `Split` and then `Join` all but the highest number? Seems terribly inefficient. – Stpete111 Aug 20 '20 at 19:52
  • 2
    @Stpete111 You could do [this](https://stackoverflow.com/a/3264855/2188407) – Justin Lessard Aug 20 '20 at 19:53
  • Yes I do believe `Take` is where I need to focus. Thanks @JustinLessard ! – Stpete111 Aug 20 '20 at 20:14
  • 1
    Besides you can write your own similar extensions. Invictus Jon Skeet [shared](https://stackoverflow.com/a/969118/13664939) it few years ago :) though without int parameter. You should add an int parameter as many character count as – gurkan Aug 20 '20 at 20:23

1 Answers1

6

If you check the purple box at the top of the Enumerable.SkipLast documentation, you'll see that it is not available in .NET Framework 4.7.2


For what it's worth, the source code is here, so you can just add it yourself. The logic is brilliant:

  • On the first call to the enumerator, count items are taken from source and added to a queue, then one is dequeued and returned.
  • On subsequent calls, the next item is added to the queue, and if that wasn't the last item in source, an item is dequeued and returned.
  • When it's done, the queue contains a cache of the last items in the source (which we wanted to skip), and it was done without knowing ahead of time how many items source contained.
public static class Extensions
{
    public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int count)
    {
        var queue = new Queue<T>();

        using (var e = source.GetEnumerator())
        {
            while (e.MoveNext())
            {
                if (queue.Count == count)
                {
                    do
                    {
                        yield return queue.Dequeue();
                        queue.Enqueue(e.Current);
                    } while (e.MoveNext());
                }
                else
                {
                    queue.Enqueue(e.Current);
                }
            }
        }
    }
}
Rufus L
  • 36,127
  • 5
  • 30
  • 43