.NET 10 以降では、IComparer<TSource>を受け入れる 2 つの拡張メソッドSystem.Linq.Queryable.MaxBy<TSource,TKey>(IQueryable<TSource>, Expression<Func<TSource,TKey>>, IComparer<TSource>)とSystem.Linq.Queryable.MinBy<TSource,TKey>(IQueryable<TSource>, Expression<Func<TSource,TKey>>, IComparer<TSource>)は廃止されています。 代わりに、 IComparer<TKey> を受け入れる新しく追加されたオーバーロードを使用してください。
コードでこれらの古い拡張メソッドを呼び出すと、コンパイル時に警告 SYSLIB0061 が生成され、通常は実行時に IndexOutOfRangeException が生成されます。
難読化の理由
IComparer<T>? comparer式パラメーターを受け入れる元のMaxByとMinByが、IComparer<T>? comparer型パラメーターのジェネリック型TSourceを使用して誤って実装されました。 これは、 Comparer<T>.Compare(T, T) メソッドに渡される値が Expression<Func<TSource, TKey>> keySelector 式パラメーターによって選択されるため、抽出された値はジェネリック型の TKeyであるため、正しくありません。
注
これは、 TSource と TKey が実際に同じ構築型である場合にのみ機能していました。 型が異なる場合、ランタイム IndexOutOfRangeException: Index が配列の範囲外でした。IQueryable<TSource> sourceに必要な拡張メソッドが見つからなかったため (たとえば、MaxByで) スローされます。
対処法
IComparer<TKey>? comparer パラメーターを受け取る新しく追加されたMaxByまたはMinByメソッドを使用します。 これらは例外をスローしません。
例えば次が挙げられます。
// 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);
警告を抑制する
古い API を使用する必要がある場合は、コードまたはプロジェクト ファイルで警告を抑制できます。
1 つの違反のみを抑制するには、ソース ファイルにプリプロセッサ ディレクティブを追加して無効にしてから、警告を再度有効にします。
// Disable the warning.
#pragma warning disable SYSLIB0061
// Code that uses obsolete API.
// ...
// Re-enable the warning.
#pragma warning restore SYSLIB0061
プロジェクト内のすべての SYSLIB0061 警告を抑制するには、プロジェクト ファイルに <NoWarn> プロパティを追加します。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
...
<NoWarn>$(NoWarn);SYSLIB0061</NoWarn>
</PropertyGroup>
</Project>
詳細については、「警告を 抑制する」を参照してください。
.NET