## Why is this an issue?

Both the `Enumerable.First` extension method and the `LinkedList<T>.First` property can be used to find the first value in a `LinkedList<T>`. However, `LinkedList<T>.First` is much faster than `Enumerable.First`. For small collections, the performance difference may be minor, but for large collections, it can be noticeable. The same applies for the `Last` property as well.

Applies to:

- LinkedList<T>.First
- LinkedList<T>.Last

### What is the potential impact?

We measured a significant improvement both in execution time and memory allocation. For more details see the `Benchmarks` section from the `More info` tab.

## How to fix it

The `First` and `Last` properties are defined on the `LinkedList` class, and the extension method call can be replaced by calling the propery instead.

### Code examples

#### Noncompliant code example

    Function GetFirst(data As LinkedList(Of Integer)) As Integer
        Return Enumerable.First(data)
    End Function

    Function GetLast(data As LinkedList(Of Integer)) As Integer
        Return Enumerable.Last(data)
    End Function

#### Compliant solution

    Function GetFirst(data As LinkedList(Of Integer)) As Integer
        Return data.First.Value
    End Function

    Function GetLast(data As LinkedList(Of Integer)) As Integer
        Return data.Last.Value
    End Function

## Resources

### Documentation

- LinkedList<T>

### Benchmarks

Method | Runtime | Mean | Standard Deviation | Allocated
--- | --- | --- | --- | ---
LastMethod | .NET 7.0 | 919,577,629.0 ns | 44,299,688.61 ns | 48504 B
LastProperty | .NET 7.0 | 271.8 ns | 15.63 ns | -
LastMethod | .NET Framework 4.6.2 | 810,316,427.1 ns | 47,768,482.31 ns | 57344 B
LastProperty | .NET Framework 4.6.2 | 372.0 ns | 13.38 ns | -

#### Glossary

- Mean
- Standard Deviation
- Allocated

The results were generated by running the following snippet with BenchmarkDotNet:

    private LinkedList<int> data;
    private Random random = new Random();

    [Params(100_000)]
    public int Size { get; set; }

    [Params(1_000)]
    public int Runs { get; set; }

    [GlobalSetup]
    public void Setup() =>
        data = new LinkedList<int>(Enumerable.Range(0, Size).Select(x => random.Next()));

    [Benchmark(Baseline = true)]
    public void LastMethod()
    {
        for (var i = 0; i < Runs; i++)
        {
            _ = data.Last();                // Enumerable.Last()
        }
    }

    [Benchmark]
    public void LastProperty()
    {
        for (var i = 0; i < Runs; i++)
        {
            _ = data.Last;                  // Last property
        }
    }

Hardware configuration:

    BenchmarkDotNet=v0.13.5, OS=Windows 10 (10.0.19045.2846/22H2/2022Update)
    11th Gen Intel Core i7-11850H 2.50GHz, 1 CPU, 16 logical and 8 physical cores
      [Host]               : .NET Framework 4.8 (4.8.4614.0), X64 RyuJIT VectorSize=256
      .NET 7.0             : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
      .NET Framework 4.6.2 : .NET Framework 4.8 (4.8.4614.0), X64 RyuJIT VectorSize=256