Starting in .NET 10, the two extension methods System.Linq.Queryable.MaxBy<TSource,TKey>(IQueryable<TSource>, Expression<Func<TSource,TKey>>, IComparer<TSource>) and System.Linq.Queryable.MinBy<TSource,TKey>(IQueryable<TSource>, Expression<Func<TSource,TKey>>, IComparer<TSource>) that accept an IComparer<TSource>
are obsolete. Please use the newly added overloads that accept an IComparer<TKey>
instead.
Calling these old extension methods in code generates warning SYSLIB0061
at compile time and typically generates a IndexOutOfRangeException at runtime.
Reason for obsoletion
The original MaxBy
and MinBy
accepting an IComparer<T>? comparer
expression parameter were incorrectly implemented using the generic type TSource
for the IComparer<T>? comparer
type parameter. This is incorrect because the values passed to the Comparer<T>.Compare(T, T) method are selected by the Expression<Func<TSource, TKey>> keySelector
expression parameter, thus the extracted value is of generic type TKey
.
Note
This would previously work only if TSource
and TKey
were actually the same constructed type. If the types were distinct then a runtime IndexOutOfRangeException: Index was outside the bounds of the array. would be thrown because the needed extension method for IQueryable<TSource> source
could not be found (for example in MaxBy).
Workaround
Use the newly added MaxBy
or MinBy
method that accepts an IComparer<TKey>? comparer
parameter. These will not throw an exception.
For example:
// This worked correctly since TKey and TSource are both int.
Enumerable.Range(1, 10)
.AsQueryable()
.MaxBy(key => (0 - key), Comparer<int>.Default);
// This would throw since TKey is string but TSource is int
// and will trigger the obsoletion warning now and would
// throw an exeception at runtime.
Enumerable.Range(1, 10)
.AsQueryable()
.MaxBy(key => key.ToString(), Comparer<int>.Default);
// This previously would not compile before to the addition of
// the new methods since TKey is string and TSource is int.
// It will now compile and execute correctly.
Enumerable.Range(1, 10)
.AsQueryable()
.MaxBy(key => key.ToString(), Comparer<string>.Default);
Suppress a warning
If you must use the obsolete API, you can suppress the warning in code or in your project file.
To suppress only a single violation, add preprocessor directives to your source file to disable and then re-enable the warning.
// Disable the warning.
#pragma warning disable SYSLIB0061
// Code that uses obsolete API.
// ...
// Re-enable the warning.
#pragma warning restore SYSLIB0061
To suppress all the SYSLIB0061
warnings in your project, add a <NoWarn>
property to your project file.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
...
<NoWarn>$(NoWarn);SYSLIB0061</NoWarn>
</PropertyGroup>
</Project>
For more information, see Suppress warnings.
.NET