繁体   English   中英

C#:params关键字与列表

[英]C#: params keyword vs. list

使用params关键字与List作为某些c#函数的输入有什么利弊?

主要是性能考虑因素和其他权衡因素。

params关键字是由C#编译器处理的语法糖。 在引擎盖下面,它实际上在转动

void Foo(params object[] a) { ... }
Foo(1,2,"THREE");

void Foo(object[] a) { ... }
Foo(new object[] { 1, 2, "THREE" })

从你所询问的性能角度来看,params调用只是更快,因为创建数组比创建List <>要快一些。 上面两个片段之间没有性能差异。

我个人在编写函数时使用params ,这些函数接受另一个程序员提供的大量输入(例如String.Format ),并且在编写获取计算机提供的数据项列表的函数时使用IEnumerable (例如File.Write )。

性能影响可以忽略不计。 担心像这样的琐碎事情的表现正是唐纳德克努特在着名的“过早优化是所有邪恶的根源”中所说的。

也就是说,提问者似乎已经注意到了,所以你走了:

1000万次迭代的结果:

params took 308 ms
list took 879 ms

从这些结果我们可以看出params数组的速度快了两倍。 一个简单的事实,你可以在一秒钟之内调用这些东西千万次 ,这意味着你完全在浪费你的时间而担心它。 使用最适合您代码的任何内容。

测试它的代码(使用VS2008在发布模式下编译和运行)

class Program
{
    const int COUNT = 10000000;

    static IEnumerable<string> m_value = null;

    static void ParamsMethod(params string[] args)
    { m_value = args; } // do something with it to stop the compiler just optimizing this method away

    static void ListMethod(List<string> args)
    { m_value = args; } // do SOMETHING with it to stop the compiler just optimizing this method away

    static void Main(string[] args)
    {
        var s = new Stopwatch();
        s.Start();
        for (int i = 0; i < COUNT; ++i)
            ParamsMethod("a", "b", "c");

        Console.WriteLine("params took {0} ms", s.ElapsedMilliseconds);

        s.Reset();
        s.Start();
        for (int i = 0; i < COUNT; ++i)
            ListMethod(new List<string> { "a", "b", "c" });

        Console.WriteLine("list took {0} ms", s.ElapsedMilliseconds);
    }
}

params关键字允许您动态地将可变数量的参数传递给函数,而不必担心编译器错误,如下所示:

public string PrefixFormatString(string p, string s, params object[] par)
{ 
    return p + string.Format(s, par);
}
...
PrefixFormatString("COM", "Output Error #{0} - Error = {1}", errNum, errStr);

如果传递列表,则必须先构建列表,然后才能传递它:

public string PrefixFormatString(string p, string s, List<object> par)
{ 
    return p + string.Format(s, par.ToArray());
}
...
List<object> l = new List<object>(new object[] { errNum, errStr });
PrefixFormatString("COM", "Output Error #{0} - Error = {1}", l);

它往往隐藏了函数所期望的数据类型的含义。

请注意,这与传递简单数组变量非常相似。 唯一的区别是编译器会将参数固定到一个数组中...我不是100%肯定,但我认为技术差异只是语法糖 - 在任何一种情况下你都真的传递了一系列的输入参数是。

好吧, params在调用时允许更好的语法,但是列表(假设你的意思是IList<> )更灵活,因为不同的类可以实现接口。 如果您需要在列表上执行接口不支持的特定操作(例如ToArray() ),则传递List<>才有意义。

好吧,使用params关键字,您可以在这样的方法中输入参数:

MethodName(1, 2, 3, 4);

但是有了列表,你会这样做:

MethodName(new List<int> {1, 2, 3, 4});

前者的语法可能比后者更清晰。 当您只传入一个参数时,这非常有用:

// params
MethodName(1);

// List
MethodName(new List<int> {1});

params是用于获取可变数量参数的函数的语言构造。 它类似于C elipses说明符 - 即printf(char* fmt, ...) 该语言支持这种操作,也可以使用它,特别是如果它使代码更容易阅读。

就个人而言,我会跳过参数。 我被它咬了一两次。 怎么样? 让我解释。

您使用此签名编写公共方法:

public static void LogInUser(string username, string password, params string[] options)

你测试它,它工作,它完成...和另一个程序集/应用程序调用你的功能。

现在,一个月后您想要更改签名以添加用户角色:

public static void LogInUser(string username, string password, string role, params string[] options)

哦,对于任何调用你的方法的东西,情况都发生

LogInUser("z@z.com", "zz", "Admin", "rememberMe", "800x600");

我可以看到两者之间的主要区别是传递给方法的参数数量是在编译时使用params ,而使用List<T>则取决于在运行时传入的列表。

是否修复在编译时必须调用方法的参数数量是pro还是con,完全取决于你的设计和意图。 根据您希望实现的目标,这两者都可以是一种好处。

Params有助于提高可读性,并且与C#中的可选参数非常接近。 如果我需要在任何时候消耗未知数量的参数,我只会亲自使用List<T>实现。

编辑:刚刚发现有关性能问题的编辑。 关于这个话题,我不确定,尽管如果你可能期望使用List<T>获得大量“参数”,而params由于必须进行编码而具有理智上限。

调用方法的程序员的性能有时可以通过params关键字的使用来改善。

(鉴于程序员的成本比计算机高得多,为什么还要考虑其他任何类型的性能。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM