代码检查: C# 14 中带有 span 参数的重载解析的重大更改
C# 14 引入了新的 内置 span 转换和类型推断规则。 这使带有 span 参数的重载适用于更多场景,但也带来了一些 重大更改。
JetBrains Rider 会识别可能受到这些重大更改影响的位置,并建议对其进行审查。 并非所有更改后的行为的出现都会在编译期间或运行时导致错误,因此无需修复所有建议。 建议在审查所有出现并修复那些可能在编译期间或运行时导致错误的问题后,禁用此检查。
先前行为
在 C# 14 之前,具有 ReadOnlySpan<T> 或 Span<T> 参数的扩展方法不能直接应用于 T[] 类型的数组。 因此,在处理数组时,编译器在方法解析期间只会选择非 span 扩展方法(例如在 System.Linq.Enumerable 类中定义的方法)。
新行为
从 C# 14 开始,接受 ReadOnlySpan<T> 或 Span<T> 参数的方法在类型推断方面的能力得到扩展,并且可以在更广泛的上下文中充当扩展方法。 因此,在诸如 System.MemoryExtensions 等库中提供的基于 span 的方法现在适用于更多场景,在这些场景中,它们可能会意外触发运行时异常。
示例
ArrayTypeMismatchException 在运行时,当为协变数组选择带有 Span<T> 的重载时:
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 官方文档中了解更多信息:
2026年 3月 25日