Разрешение перегрузки C# 14 с параметрами диапазона
C# 14, который поставляется с .NET 10, представляет новые встроенные преобразования диапазонов и правила вывода типов. Эти изменения делают перегрузки с параметрами диапазона применимыми в большем количестве сценариев.
Предыдущее поведение
В C# 13 и более ранних версиях метод расширения, принимаюющий ReadOnlySpan<T>
или Span<T>
приемник, не применим к значению типа T[]
. Поэтому в лямбда-выражениях обычно связывались только методы расширения, не работающие с диапазонами, например, из класса System.Linq.Enumerable
.
Новое поведение
В C# 14 и более поздних версиях методы с параметрами ReadOnlySpan<T>
или Span<T>
могут участвовать в выводе типов или использоваться в качестве методов расширения в дополнительных сценариях. Это делает методы на основе диапазона, такие как те из класса System.MemoryExtensions
, применимыми в большем числе сценариев, в том числе внутри лямбда-выражений, где они будут вызывать исключения во время выполнения при интерпретации компиляции.
Представленная версия
.NET 10 (предварительная версия 1)
Тип изменения, нарушающего совместимость
Это изменение является изменением в поведении.
Причина изменения
Функция языка C# позволяет упростить проектирование и использование API (например, один метод расширения ReadOnlySpan<T> может применяться как к диапазонам, так и к массивам).
Рекомендуемое действие
Если необходимо продолжить использование обработки выражений, убедитесь, что перегрузки, не относящиеся к диапазону, привязаны, например, путем приведения аргументов к точным типам, которые принимает сигнатура метода, или вызвать методы расширения в виде явных статических вызовов:
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);