考虑以下结构:
public struct vip
{
string email;
string name;
int category;
public vip(string email, int category, string name = "")
{
this.email = email;
this.name = name;
this.category = category;
}
}
以下两个电话之间是否存在性能差异?
var e = new vip(email: "foo", name: "bar", category: 32);
var e = new vip("foo", 32, "bar");
如果没有定义可选参数会有区别吗?
答案 0 :(得分:5)
我相信没有。它只是一种语言/编译器功能,如果你愿意,可以称它为语法糖。生成的CLR代码应该相同。
答案 1 :(得分:3)
有编译时的成本,但不是运行时成本......编译时间非常,非常分钟。
与extension methods或auto-implemented properties一样,这只是编译器的魔力,但实际上会生成相同的IL,我们都熟悉并且已经使用了多年。
以这种方式思考,如果你使用所有参数,编译器会使用所有参数调用方法,如果不是,它会在幕后产生类似的东西:
var e = new vip(email: "foo", category: 32); //calling
//generated, this is what it's actually saving you from writing
public vip(string email, int category) : this(email, category, "bar") { }
答案 2 :(得分:1)
应该没有。基本上,命名参数和可选参数是语法糖;编译器将实际值或默认值直接写入调用站点。
编辑:请注意,因为它们是编译器功能,这意味着只有在重新编译“客户端”时才会更新参数更改。因此,例如,如果更改可选参数的默认值,则需要重新编译所有“客户端”,否则它们将使用旧的默认值。
答案 3 :(得分:1)
不,它只是一个编译时功能。如果检查生成的IL,您将看不到命名参数的迹象。同样,可选参数也是编译时功能。
关于命名参数要记住的一件事是,名称现在是编译时调用方法(如果明显使用)的签名的一部分。即如果名称发生更改,则重新编译时也必须更改调用代码。另一方面,部署的程序集在重新编译之前不会受到影响,因为IL中不存在名称。
答案 4 :(得分:1)
实际上,x64 CLR有成本
请看http://www.dotnetperls.com/named-parameters
我能够重现结果:命名调用需要4.43 ns,正常调用需要3.48 ns (程序在x64中运行)
然而,在x86中,两者都需要大约0.32 ns
代码附在下面,编译并自己运行以查看差异。
请注意,在VS2012中,默认的targat是AnyCPU x86首选,你必须切换到x64才能看到差异。
using System;
using System.Diagnostics;
class Program
{
const int _max = 100000000;
static void Main()
{
Method1();
Method2();
var s1 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
Method1();
}
s1.Stop();
var s2 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
Method2();
}
s2.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000 * 1000) /
_max).ToString("0.00 ns"));
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000 * 1000) /
_max).ToString("0.00 ns"));
Console.Read();
}
static void Method1()
{
Method3(flag: true, size: 1, name: "Perl");
}
static void Method2()
{
Method3(1, "Perl", true);
}
static void Method3(int size, string name, bool flag)
{
if (!flag && size != -1 && name != null)
{
throw new Exception();
}
}
}