代码检查:C# 14 中带有 span 参数的重载解析中的重大更改
C# 14 引入了新的 内置 span 转换和类型推导规则。 它使带有 span 参数的重载在更多场景下适用,但也带来了一些 重大更改。
ReSharper 会识别可能受这些重大更改影响的位置,并建议对其进行审查。 并非所有发生了变化的行为都会在编译或运行时引发错误,因此无需修复所有建议。 建议在审查了所有情况并修复那些可能在编译或运行时引发错误的问题后,禁用此检查。
先前的行为
在 C# 14 之前,具有 ReadOnlySpan<T> 或 Span<T> 参数的扩展方法无法直接应用于 T[] 类型的数组。 因此,在处理数组时,编译器在方法解析过程中只会选择非 span 的扩展方法(例如定义在 System.Linq.Enumerable 类中的那些)。
新的行为
从 C# 14 开始,接受 ReadOnlySpan<T> 或 Span<T> 参数的方法在类型推导方面的能力已被扩展,可在更多上下文中用作扩展方法。 因此,像在 System.MemoryExtensions 这样的库中基于 span 的方法在更多场景下可适用,但这些场景中可能会意外触发运行时异常。
示例
在运行时为协变数组选择带有 Span<T> 的重载时, ArrayTypeMismatchException。
string[] strings = new[] { "a" };
M(strings);
void M(object[] possibleCovariantArray)
{
// ok with C# 13 because it uses overload with IEnumerable<T>,
// but in C# 14, ArrayTypeMismatchException is thrown at runtime
// when converting a covariant array to Span<object>
Util.DoSomething(possibleCovariantArray);
}
static class Util
{
public static void DoSomething<T>(IEnumerable<T> e) =>
Console.Write("IEnumerable<T>");
public static void DoSomething<T>(Span<T> s) =>
Console.Write("Span<T>");
}
由于重载解析的变化导致的编译错误:
string[] strings = new[] { "a" };
// C# 13 uses overload with IEnumerable<T>, which has a return type,
// but C# 14 uses overload with Span<T>, which has no return type
_ = strings.Reverse();
static class Util
{
public static IEnumerable<T> Reverse<T>(this IEnumerable<T> e) =>
throw new NotImplementedException();
public static void Reverse<T>(this Span<T> s) =>
throw new NotImplementedException();
}
在以解释方式编译表达式 lambda 时出现运行时异常:
using System.Linq.Expressions;
// ok with C# 13, but causes a runtime exception in C# 14
// because it uses overload with ReadOnlySpan<T>
M((array, num) => array.Contains(num));
void M(Expression<Func<int[], int, bool>> e) =>
e.Compile(preferInterpretation: true);
在 Microsoft 官方文档中了解更多信息:
最后修改日期: 2025年 12月 8日