Поделиться через


Разрешение перегрузки 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);

Затронутые API