Partilhar via


SYSLIB0061: System.Linq.Queryable.MaxBy e System.Linq.Queryable.MinAo tomar um IComparer<TSource> estão obsoletos

A partir do .NET 10, os dois métodos System.Linq.Queryable.MaxBy<TSource,TKey>(IQueryable<TSource>, Expression<Func<TSource,TKey>>, IComparer<TSource>) de extensão e System.Linq.Queryable.MinBy<TSource,TKey>(IQueryable<TSource>, Expression<Func<TSource,TKey>>, IComparer<TSource>) que aceitam um IComparer<TSource> são obsoletos. Por favor, use as sobrecargas recém-adicionadas que aceitam um em vez disso IComparer<TKey> .

Chamar esses métodos de extensão antigos no código gera aviso SYSLIB0061 em tempo de compilação e normalmente gera um IndexOutOfRangeException tempo de execução.

Motivo da obsolescência

O parâmetro original MaxBy e MinBy aceitando uma IComparer<T>? comparer expressão foram implementados incorretamente usando o tipo TSource genérico para o IComparer<T>? comparer parâmetro type. Isso é incorreto porque os valores passados para o Comparer<T>.Compare(T, T) método são selecionados pelo Expression<Func<TSource, TKey>> keySelector parâmetro expression, portanto, o valor extraído é do tipo TKeygenérico.

Observação

Isso funcionaria anteriormente apenas se TSource e TKey fosse realmente o mesmo tipo construído. Se os tipos fossem distintos, então um tempo de execuçãoIndexOutOfRangeException: O índice estava fora dos limites da matriz. seria lançado porque o método de extensão necessário para IQueryable<TSource> source não pôde ser encontrado (por exemplo, em MaxBy).

Solução

Use o método recém-adicionado MaxBy ou MinBy que aceita um IComparer<TKey>? comparer parâmetro. Estes não abrirão uma exceção.

Por exemplo:

// 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);

Suprimir um aviso

Se você precisar usar a API obsoleta, poderá suprimir o aviso no código ou no arquivo de projeto.

Para suprimir apenas uma única violação, adicione diretivas de pré-processador ao arquivo de origem para desativar e reativar o aviso.

// Disable the warning.
#pragma warning disable SYSLIB0061

// Code that uses obsolete API.
// ...

// Re-enable the warning.
#pragma warning restore SYSLIB0061

Para suprimir todos os avisos de SYSLIB0061 em seu projeto, adicione uma propriedade <NoWarn> ao seu arquivo de projeto.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
   ...
   <NoWarn>$(NoWarn);SYSLIB0061</NoWarn>
  </PropertyGroup>
</Project>

Para obter mais informações, consulte Suprimir avisos.