使用 C# 13 参数集合可以更轻松、更快速地调用方法

摘要:C# 13 提供的功能让您能够更轻松、更安全、更快速地以您熟悉和喜爱的风格编写代码。您可以在 C# 13 中的新增功能中找到 C# 13 功能的完整列表。

作者:Kathleen Dollard

排版:Rani Sun

C# 13 提供的功能让您能够更轻松、更安全、更快速地以您熟悉和喜爱的风格编写代码。您可以在 C# 13 中的新增功能中找到 C# 13 功能的完整列表。

C# 13 实现了一项长期以来的功能请求,现在允许集合表达式支持的任何集合类型作为params参数,而不仅仅是数组。此功能基于 C# 12 中引入的集合表达式功能。

C# 13 中的新增功能

https://learn.microsoft.com/dotnet/csharp/whats-new/csharp-13

使用集合表达式奠定基础

C# 12 中引入了集合表达式,为以前创建各种集合的无数种方法提供了一种替代方法。在方法上下文中,这允许您在许多场景中简化集合的使用,包括调用方法:

// C# 12 之前WritebyteArray(new { (byte)1, (byte)2, (byte)3 });WriteByteSpan(stackalloc { (byte)1, (byte)2, (byte)3 });// C# 12 之后WriteByteArray([1, 2, 3]);WriteByteSpan([1, 2, 3]);static void WriteByteArray(byte bytes) { }static void WriteByteSpan(Span bytes) { }

这也使我们能够统一 C# 处理集合的方式。请注意,集合表达式可以推断集合的类型和成员的类型。

params数组

params 自 C# 1.0 以来就一直存在于该语言中。它允许调用代码以逗号分隔的列表形式包含零到多个参数。该方法以数组形式接收此列表,该列表可能为空:

WriteByteArray(1, 2, 3);WriteByteArray;static void WriteByteArray(params byte bytes) { }

在 C# 13 之前,必须在方法的参数列表中将 params 声明为数组。

除了使用值列表进行调用外,您还可以使用数组调用带有 params 参数的方法。并且从 C# 12 开始,它可以是集合表达式:

WriteByteArray(1, 2, 3);WriteByteArray([1, 2, 3]);byte bytes = [4, 5];WriteByteArray([1, 2, 3, .. bytes]);

params 集合

从 C# 13 开始,params 可以是任何支持集合表达式的集合类型:

WriteByteSpan(1, 2, 3);WriteByteSpan;static void WriteByteSpan(params Span bytes) { }

虽然这似乎是一个很小的变化,但它通常可以让编译器优化您的代码。例如,如果该方法使用 params Span,则编译器可以使用堆栈空间为该方法创建Span。这比分配数组的性能更好。

使用特定类型还可以向调用者传达集合的使用方式。例如,params IReadonlyList表示集合不会被修改。

如果您使用 params IEnumerable,则用户可以传递文字值列表、数组、List、任何实现 IEnumerable的集合类型或 LINQ 表达式:

WriteByteArray(1, 2, 3);byte bytes = [1, 2, 3, 4, 5];WriteByteArray(bytes.Where(x => x static void WriteByteArray(params IEnumerable bytes) { }

当 params 接收器是接口并且参数是元素的离散列表或集合表达式时,编译器将使用具体类型。许多集合接口都有一个逻辑上合理的默认实现,例如 IReadonlyList对应ReadonlyCollection。由于 IEnumerable没有如此明显的选择,并且对 .NET 至关重要,因此它对 param 和集合表达式都使用了一种特殊的高性能类型。

重载

C# 支持重载方法 - 这意味着如果参数类型不同,则可以存在多个同名方法。您可以像重载其他参数一样对 params 集合进行重载。

public class ParamCollections{ public static void Overloads { WriteNumbers(1, 2, 3); WriteNumbers([1, 2, 3]); WriteNumbers(new { 1, 2, 3 }); byte ints = [1, 2, 3, 4, 5]; WriteNumbers(ints.Where(x => x } // 此代码从静态本地函数转变为私有函数 // 因为局部函数不允许重载。 private static void WriteNumbers(params IEnumerable values) => Console.WriteLine("IEnumerable"); private static void WriteNumbers(params ReadOnlySpan values) => Console.WriteLine("Span");}// 结果是:// // Span// Span// Span// IEnumerable

例如,您可能在同一个解析范围内有一个带有 params IEnumerable的重载和一个带有 params ReadOnlySpan的重载。如果您传递一个值列表,则将选择 params ReadOnlySpan重载。如果您传递一个数组,则也将选择 params ReadOnlySpan重载,因为从数组到 ReadOnlySpan存在隐式转换。如果您传递 List,则将使用 params IEnumerable重载:

}

编译器会为您挑选一个合理的重载。如果 Span可用,它通常会被优先选择,因为这样可以避免在方法调用中进行内存分配。

无论您是否将 params 集合添加到您自己的代码中,它们都会使您的应用程序运行得更快,因为 .NET 运行时库现在可以在更多地方使用 Span等高性能类型。您可以使用与 params 相同的概念,调用者在如何调用方法方面具有更大的灵活性,并且编译器将选择重载。

考虑重载

重载是 C# 的一个非常强大的功能。但与许多强大的功能一样,正确使用它非常重要。如果有多个同名的方法,它们应该执行相同的操作。它们在执行方式或性能上可能有所不同,但更改传递的类型不会给您的应用程序带来重大更改。通常,这意味着在调整参数值后调用单个实现。

如上例所示,调用代码的微小变化可能会导致调用不同的重载。对于所有 C# 应用程序来说都是如此,无论您是否使用 params 集合。

总结

我们对 C# 13 中的参数集合感到非常兴奋,迫不及待地想听听您的想法!

您可以在 C# 13 中的新增功能中了解 C# 13 中的所有功能。

C# 13 中的新增功能

https://devblogs.microsoft.com/semantic-kernel/microsoft-extensions-ai-simplifying-ai-integration-for-net-partners/

来源:opendotnet

相关推荐