Udostępnij przez


Rozdzielczość przeciążenia języka C# 14 z parametrami zakresu

Język C# 14, który jest dostarczany z platformą .NET 10, wprowadza nowe wbudowane konwersje zakresów i reguły wnioskowania typów. Te zmiany sprawiają, że przeciążenia z parametrami zakresu mają zastosowanie w większej liczbie scenariuszy.

Poprzednie zachowanie

W języku C# 13 i starszych metoda rozszerzenia przyjmująca ReadOnlySpan<T> lub odbiornik Span<T> nie miała zastosowania do wartości typu T[]. W związku z tym tylko niespanowe metody rozszerzenia, takie jak te z klasy System.Linq.Enumerable, były zwykle powiązane wewnątrz wyrażeń lambda.

Nowe zachowanie

W C# 14 i nowszych metody z parametrami ReadOnlySpan<T> lub Span<T> mogą uczestniczyć w wnioskowaniu typu lub być używane jako metody rozszerzenia w większej liczbie scenariuszy. Dzięki temu metody oparte na zakresie, takie jak te z klasy System.MemoryExtensions, są używane w większej liczbie scenariuszy, w tym wewnątrz wyrażeń lambda, gdzie spowodują wyjątki w czasie wykonywania, gdy zostaną skompilowane z użyciem interpretacji.

Wersja wprowadzona

.NET 10

Rodzaj zmiany łamiącej zgodność

Ta zmiana jest zmianą behawioralną.

Przyczyna zmiany

Funkcja języka C# umożliwia uproszczone projektowanie i użycie interfejsu API (na przykład jedna metoda rozszerzenia ReadOnlySpan<T> może być stosowana zarówno do zakresów, jak i tablic).

Jeśli musisz kontynuować korzystanie z interpretacji wyrażenia, upewnij się, że przeciążenia inne niż span są powiązane, na przykład przez rzutowanie argumentów do dokładnych typów, które podpis metody przyjmuje lub wywołuje metody rozszerzenia jako jawne wywołania statyczne:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

M((array, num) => array.Contains(num)); // fails, binds to MemoryExtensions.Contains
M((array, num) => ((IEnumerable<int>)array).Contains(num)); // ok, binds to Enumerable.Contains
M((array, num) => array.AsEnumerable().Contains(num)); // ok, binds to Enumerable.Contains
M((array, num) => Enumerable.Contains(array, num)); // ok, binds to Enumerable.Contains

void M(Expression<Func<int[], int, bool>> e) => e.Compile(preferInterpretation: true);

Interfejsy API, których dotyczy problem