NDepend Blog

Improve your .NET code quality with NDepend

Top 10 New .NET 6.0 API

July 7, 2021 5 minutes read


.NET 6 introduces new handy APIs that will make our development journey easier. Let’s go through the top 10 new API in terms of usage likelyhood.

Then in the conclusion, we’ll provide the complete list of new .NET 6 API compared against .NET 5.

DateOnly and TimeOnly

Until now DateTime and TimeSpan were the only .NET Base Class Library choice to handle time operations. .NET 6.0 introduce two new structures: TimeOnly and DateOnly. Those are welcome because it was awkward to use DateTime to handle the concepts of time-of-day, and date without time. Here is some sample code to illustrate the usage of these structures. Notice that the strings obtained with ToString() might differ depending on your globalization settings:

Notice that if your application must deal with tricky date concepts, like a partial date (7th of July or July 2021 for example), it is still recommended to use the OSS project NodaTime.

Still related to date, .NET 6.0 brings up some Time Zone Conversion APIs improvement. You can read more on the official MSDN blog post.

New collection: PriorityQueue<TElement,TPriority>

A new PriorityQueue<TElement,TPriority> class is proposed in .NET 6. It is illustrated by this simple example:

It has been decided that the priority of an item cannot be changed. With this condition the PriorityQueue implementation can be way faster.

Also for performance reasons, it has also been decided that the PriorityQueue implementation is not necessarily stable. A priority queue is stable if items with the same priority are dequeued in the same enqueue order.

Unlike many collections, PriorityQueue doesn’t implement IEnumerable<TElement>. This is because an enumerator on a PriorityQueue would need to remember somehow what was the last item’s priority dequeue. Scenarios with multiples enumerators and a queue that gets new prioritized elements could lead to awkward situations. Instead PriorityQueue proposes the property UnorderedItems.

LINQ now works with Index and Range operators

.NET 6 improves LINQ to make it work with the C# index ^ and range .. operators introduced with C#8. Those operators are full explained here. Here are some new extension methods:

See those in action here:

FirstOrDefault(), LastOrDefault() SingleOrDefault() now lets specify the default value

Until now these extension method necessarily returned default(T). You can now specify the default value. For example:

MaxBy(), MinBy(), DistinctBy(), UnionBy(), IntersectBy(), ExceptBy()

Those address what this popular stackoverflow question addressed (288K views since 2009): How to use LINQ to select object with minimum or maximum property value

Let’s illustrate the new By methods with some code:

Non-enumerating Count Linq Method

Internally, the well know Count(this IEnumerable<T>) first checks if this sequence can be casted to a ICollection<T>. If so the ICollection<T>Count method can immediately return the count value. Else the Count() method must iterate through all items in the sequence. Doing so can be a performance killer for example when iterating a sequence pointing to a database. This is why the new .NET 6 method bool TryGetNonEnumeratedCount(this IEnumerable<T> source, out int count) only returns true when counting is cheap.

Batching a sequence

A common scenario is the need to batch a sequence into chunks of defined size. This operation is not so easy to implement since the last chunk size cannot be 0 but from 1 to defined chunk size. Hence .NET 6 introduces these 2 extensions methods:

For example:

Zipping 3 sequences

Until now it was possible to zip 2 sequences. .NET 6 makes possible to zip 3 sequences thanks to these new methods:

Here is an example:

In this proposal discussion, we can see that the team decided that it wasn’t necessary to provide higher arities than 3.

>Let’s support only three for now as four seems fairly rare.

List<T>, Stack<T>, Queue<T>, EnsureCapacity() method

A method EnsureCapacity() has been added to List<T>, Stack<T> and Queue<T> classes. Each of these collections maintain internally an array to store items. The array size is the collection capacity. Obviously the capacity gets increased when adding one or several items is provoking an array length overflow. Such array resizing operation represents a performance hit. Thus when you know the final size of a collection to be filled, you can directly ensure its capacity and avoid multiple costly array resizing operations.

New WaitAsync Methods

New Task.WaitAsync() methods are proposed to cancel waiting for a task to complete. Let’s underline that when the time-out or the CancellationToken expires, the task on which we wait doesn’t get cancelled. Only the wait operation gets cancelled.


.NET 6 proposes more new API.

Actually NDepend v2021.2 (to be released after the summer) will propose a new OSS Power Tool based on NDepend.API and diff capabilities to explore new .NET 6 APIs. This tool will be easily adaptable to future new .NET versions. Here is what the power tool finds when comparing .NET 6 preview 4 against .NET 5.0.6.


Here is the list of all new public types.

Here is the list of all new public fields declared in types that already existed in .NET 5.

Here is the list of all new public methods declared in types that already existed in .NET 5.


  1. Mike Ober says:

    Years ago I wrote a priority queue in VB using the sorted dictionary class as the base. It took two pages of code and supported the Ienumerable interface. Seriously lazy on the part of the framework developers.

Comments are closed.