[translation] LINQ improvement in NET 6

Posted by jphilapy on Tue, 18 Jan 2022 06:03:53 +0100

introduce

Next, I will give you a key introduction Net 6. The articles are all articles from foreign bigwigs. I will translate them and add some of my own understanding and explanation.

Source Author link: https://blog.okyrylchuk.dev/linq-improvements-in-net-6

text

*Default value of OrDefault method

Enumerable. The firstordefault method returns the first element of the sequence. If no element is found, it returns the default value. Yes NET 6, you can override the default values. You can also override the default values of the SingleOrDefault and LastOrDefault methods.

List<int> list1 = new() { 1, 2, 3 };
int item1 = list1.FirstOrDefault(i => i == 4, -1);
Console.WriteLine(item1); // -1

List<string> list2 = new() { "Item1" };
string item2 = list2.SingleOrDefault(i => i == "Item2", "Not found");
Console.WriteLine(item2); // Not found

New * sorting method

. NET 6 introduces a new Enumerable. By * sorting method. A "keySelector" is provided to compare elements
new method:

  • MinBy
  • MaxBy
  • DistinctBy
  • ExceptBy
  • IntersectBy
  • UnionBy
List<Product> products = new()
{
    new() { Name = "Product1", Price = 100 },
    new() { Name = "Product2", Price = 5 },
    new() { Name = "Product3", Price = 50 },
};

Product theCheapestProduct = products.MinBy(x => x.Price);
Product theMostExpensiveProduct = products.MaxBy(x => x.Price);
Console.WriteLine(theCheapestProduct);
// Output: Product { Name = Product2, Price = 5 }
Console.WriteLine(theMostExpensiveProduct);
// Output: Product { Name = Product1, Price = 100 }

record Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

A new blocking method

If you need to split the elements of a sequence into blocks, you don't have to NET 6. It introduces a new enumerable Chunk extension method.

IEnumerable<int> numbers = Enumerable.Range(1, 505);
IEnumerable<int[]> chunks = numbers.Chunk(100);

foreach (int[] chunk in chunks)
{
    Console.WriteLine($"{chunk.First()}...{chunk.Last()}");
}

//  Output:
//  1...100
//  101...200
//  201...300
//  301...400
//  401...500
//  501...505

Three way zipper method

Enumerable. The zip extension method generates a tuple sequence containing elements from two specified sequences. Yes NET 6, it can combine tuples from three sequences.

It cannot combine tuples from four or more sequences.

int[] numbers = { 1, 2, 3, 4, };
string[] months = { "Jan", "Feb", "Mar" };
string[] seasons = { "Winter", "Winter", "Spring" };

var test = numbers.Zip(months).Zip(seasons);

foreach ((int, string, string) zipped in numbers.Zip(months, seasons))
{
    Console.WriteLine($"{zipped.Item1} {zipped.Item2} {zipped.Item3}");
}
// Output:
// 1 Jan Winter
// 2 Feb Winter
// 3 Mar Spring

Index support in ElementAt method

. NET Core 3.0 introduces the Index structure, which is used by the C# compiler to support the new unary prefix "hat" operator (^). This means that the Index is "from the end of the collection". Yes NET 6, enumerable Elementat method supports Index.

IEnumerable<int> numbers = new int[] { 1, 2, 3, 4, 5 };
int last = numbers.ElementAt(^0);
Console.WriteLine(last); // 5

Scope support in Take method

The Range structure is already in use NET Core 3.0. The C# compiler uses it to support the Range operator '..'

Yes NET 6, enumerable The take method supports Range.

IEnumerable<int> numbers = new int[] { 1, 2, 3, 4, 5 };

IEnumerable<int> taken1 = numbers.Take(2..4);
foreach (int i in taken1)
    Console.WriteLine(i);
// Output:
// 3
// 4

IEnumerable<int> taken2 = numbers.Take(..3);
foreach (int i in taken2)
    Console.WriteLine(i);
// Output:
// 1
// 2
// 3

IEnumerable<int> taken3 = numbers.Take(3..);
foreach (int i in taken3)
    Console.WriteLine(i);
// Output:
// 4
// 5

Use TryGetNonEnumeratedCount to avoid enumeration

. NET 6 introduces a new enumerable Trygetnonenumerated method. Let's calculate the total number of enumerable type elements.

TryGetNonEnumeratedCount method, which means that if you can count quickly, the method will return true and return the count as an out variable.

IEnumerable<int> numbers = GetNumbers();
TryGetNonEnumeratedCount(numbers);
// Output: Could not get a count of numbers without enumerating the sequence 

IEnumerable<int> enumeratedNumbers = numbers.ToList();

var test = enumeratedNumbers.ElementAt(-1);

TryGetNonEnumeratedCount(enumeratedNumbers);
// Output: Count: 5

void TryGetNonEnumeratedCount(IEnumerable<int> numbers)
{
    if (numbers.TryGetNonEnumeratedCount(out int count))
        Console.WriteLine($"Count: {count}");
    else
        Console.WriteLine("Could not get a count of numbers without enumerating the sequence");
}

IEnumerable<int> GetNumbers()
{
    yield return 1;
    yield return 2;
    yield return 3;
    yield return 4;
    yield return 5;
}

epilogue

Contact author: Jia Qun: 867095512 @ mrchujiu