c# - 为什么 params 'less performant' 不是常规数组?

标签 c# parameters variadic-functions

如果您现在开始在您的 IDE 中输入 string.Format,您会看到有 4 种不同的重载:一种采用字符串和对象,另一种采用字符串和两个对象,然后一个接受三个对象,最后一个使用 params。根据this answer ,这是因为 params 会产生“开销”,其他一些语言可能不支持它。

我的问题是,为什么不能这样调用方法:

void Foo()
{
    Bar(1, 2, 3);
}

void Bar(params int[] args)
{
    // use args...
}

在编译时本质上被转换为

void Foo()
{
    Bar(new[] { 1, 2, 3 });
}

void Bar(int[] args)
{
    // use args...
}

?然后它不会产生任何开销,除了创建数组(这是必需的),并且与其他语言完全兼容。

参数的数量在编译时已知,那么是什么阻止了 C# 编译器进行某种字符串替换并使第一个场景本质上成为第二个场景的语法糖?为什么我们必须实现 hidden language features专门支持可变参数?

最佳答案

标题做出了错误的假设。

参数和非参数方法都采用数组;不同之处在于编译器会发出 IL 以在进行 params 方法调用时隐式创建数组。 一个数组作为单个参数传递给两个方法

can be seen in this .NET Fiddle (查看“整理 -> 查看 IL”)。

using System;

public class Program
{
    public static void Main()
    {
        var a1 = 1;
        var a2 = 2;
        var a3 = 3; 
        with_params(a1,a2,a3);
        no_params(new [] {a1,a2,a3});
    }

    public static void with_params(params int[] x) {}
    public static void no_params(int[] x) {}
}

两种情况中,IL 是相同的;创建一个新数组,填充它,并将该数组提供给调用的方法。

这个相同的 IL 生成有一个“异常(exception)”,即当以非参数形式使用时,编译器可以移出常量值数组并使用“dup”初始化,as seen here .但是,在这两种情况下,都提供了一个数组作为参数。

关于c# - 为什么 params 'less performant' 不是常规数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31496753/

相关文章:

function - Elixir 函数有最大的 Airty 吗?

c# - 在 Entity Framework 中合并

c# - 在 C++ 中使用非常 C# 的 DLL

c# - C# 中的字符串到字典或数组

node.js - 将参数传递给 package.json 中的 npm 脚本

java - 请求 URL 参数破坏输入流 Java

swift - 开括号后的参数

c++ - 从参数包中排除前 n 个参数

c# - Sqlite "No such table"保存对象时

java - 具有对象和原始类型的模糊可变参数方法