简体   繁体   English

C#:params关键字与列表

[英]C#: params keyword vs. list

What are the pro/cons of using the params keyword vs. a List as input to some c# function? 使用params关键字与List作为某些c#函数的输入有什么利弊?

Mainly what are the performance considerations and other trade offs. 主要是性能考虑因素和其他权衡因素。

The params keyword is syntactic sugar handled by the C# compiler. params关键字是由C#编译器处理的语法糖。 underneath the hood, it's actually turning 在引擎盖下面,它实际上在转动

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

into

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

From a performance perspective like you're asking about, the params call is simply faster because it is a bit faster to create an array than it is to create a List<>. 从你所询问的性能角度来看,params调用只是更快,因为创建数组比创建List <>要快一些。 There is no performance difference between the two snippets above. 上面两个片段之间没有性能差异。

Personally I use params when writing functions that take a number of inputs provided by another programmer (for example String.Format ), and IEnumerable when writing functions that take a list of data items provided by the computer (for example File.Write ). 我个人在编写函数时使用params ,这些函数接受另一个程序员提供的大量输入(例如String.Format ),并且在编写获取计算机提供的数据项列表的函数时使用IEnumerable (例如File.Write )。

The performance implications are negligible. 性能影响可以忽略不计。 Worrying about the performance of a trivial thing like this is exactly what Donald Knuth was talking about in the famous "premature optimization is the root of all evil" quote. 担心像这样的琐碎事情的表现正是唐纳德克努特在着名的“过早优化是所有邪恶的根源”中所说的。

That said, the asker seems to be fixated on it, so here you go: 也就是说,提问者似乎已经注意到了,所以你走了:

Results for 10 million iterations: 1000万次迭代的结果:

params took 308 ms
list took 879 ms

From these results we can see that the params array is just over twice as fast. 从这些结果我们可以看出params数组的速度快了两倍。 The simple fact that you can call either of these things Ten Million Times in under a second means that you're completely wasting your time by worrying about it. 一个简单的事实,你可以在一秒钟之内调用这些东西千万次 ,这意味着你完全在浪费你的时间而担心它。 Use whatever suits your code the best. 使用最适合您代码的任何内容。

The code to test it (compiled and run in release mode using VS2008) 测试它的代码(使用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);
    }
}

The params keyword allows you to dynamically pass a variable number of arguments to the function without worrying about compiler errors like this: 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);

If you pass a list, you have to construct the list before you can pass it in: 如果传递列表,则必须先构建列表,然后才能传递它:

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);

and it tends to hide the meaning of what type of data the function is expecting. 它往往隐藏了函数所期望的数据类型的含义。

Note that this is very similar to passing a simple array variable. 请注意,这与传递简单数组变量非常相似。 The only difference is that the compiler will fix up the parameters into an array for you... I'm not 100% sure, but I think the technical difference is just syntactical sugar - in either case you are really passing an array of whatever type the parameter is. 唯一的区别是编译器会将参数固定到一个数组中...我不是100%肯定,但我认为技术差异只是语法糖 - 在任何一种情况下你都真的传递了一系列的输入参数是。

Well, the params allows for a nicer syntax when calling it, but the list (assuming you mean IList<> ) is more flexible because different classes may implement the interface. 好吧, params在调用时允许更好的语法,但是列表(假设你的意思是IList<> )更灵活,因为不同的类可以实现接口。 Passing a List<> only makes sense if you need to perform specific operations on the list which are not supported by the interface (such as ToArray() ). 如果您需要在列表上执行接口不支持的特定操作(例如ToArray() ),则传递List<>才有意义。

Well, with the params keyword you could enter arguments into a method like this: 好吧,使用params关键字,您可以在这样的方法中输入参数:

MethodName(1, 2, 3, 4);

But with a list, you'd do it like this: 但是有了列表,你会这样做:

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

The syntax can be a bit more clear in the former than the latter. 前者的语法可能比后者更清晰。 This is useful when you just have one parameter to pass in: 当您只传入一个参数时,这非常有用:

// params
MethodName(1);

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

params is a language construct for functions taking a variable number of parameters. params是用于获取可变数量参数的函数的语言构造。 It is similar to C elipses specifier - ie printf(char* fmt, ...) . 它类似于C elipses说明符 - 即printf(char* fmt, ...) The language supports this kind of operation, might as well use it, especially if it makes the code easier to read. 该语言支持这种操作,也可以使用它,特别是如果它使代码更容易阅读。

Personally, I would skip the params. 就个人而言,我会跳过参数。 I've been bitten by it once or twice. 我被它咬了一两次。 How? 怎么样? Let me explain. 让我解释。

You write a public method with this signature: 您使用此签名编写公共方法:

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

You test it, it works, its done... and another assembly/application is calling your function. 你测试它,它工作,它完成...和另一个程序集/应用程序调用你的功能。

Now, a month later you want to change your signature to add user role: 现在,一个月后您想要更改签名以添加用户角色:

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

Oh how things have changed for anything calling your method. 哦,对于任何调用你的方法的东西,情况都发生

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

The main difference between the two that I can see is that the number of parameters passed into the method is set at compile time using params , while with a List<T> it depends on the list passed in at runtime. 我可以看到两者之间的主要区别是传递给方法的参数数量是在编译时使用params ,而使用List<T>则取决于在运行时传入的列表。

Whether fixing the number of arguments that your method must be called with at compile time is a pro or a con depends entirely upon your design and intent for it. 是否修复在编译时必须调用方法的参数数量是pro还是con,完全取决于你的设计和意图。 Either can be a benefit depending on what you are hoping to achieve. 根据您希望实现的目标,这两者都可以是一种好处。

Params helps on the readability front, and is as close to an optional parameter that you're going to get to in C#. Params有助于提高可读性,并且与C#中的可选参数非常接近。 I would only use the List<T> implementation personally if I needed to consume an unknown number of parameters at any point. 如果我需要在任何时候消耗未知数量的参数,我只会亲自使用List<T>实现。

Edit: just spotted your edit regarding performance issues. 编辑:刚刚发现有关性能问题的编辑。 On that topic I'm unsure, although if you could potentially expect a large number of 'parameters' using List<T> , whereas params has a sanity cap on it due to them having to be coded. 关于这个话题,我不确定,尽管如果你可能期望使用List<T>获得大量“参数”,而params由于必须进行编码而具有理智上限。

The performance of the programmer calling your method can sometimes be improved by your usages of the params keyword. 调用方法的程序员的性能有时可以通过params关键字的使用来改善。

(Given that programmers cost so much more then computers, why are you thinking of any other sort of performance.) (鉴于程序员的成本比计算机高得多,为什么还要考虑其他任何类型的性能。)

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

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