C# NET中属性的性能开销
我在某个地方读到,拥有公共属性比在类中拥有公共成员更可取C# NET中属性的性能开销,c#,.net,performance,C#,.net,Performance,我在某个地方读到,拥有公共属性比在类中拥有公共成员更可取 这仅仅是因为抽象性和模块性吗?是否还有其他过度驾驶的原因 编译器将属性访问转换为函数调用。对于没有备份存储的属性(例如,公共字符串用户名{get;set;}),与直接成员访问相比,性能开销是多少?(我知道这通常不会有什么不同,但在我的一些代码中,属性被访问了数百万次。) 编辑1: 我在整数成员和属性上运行了一些测试代码,公共成员的速度大约是属性的3-4倍。(调试中约57毫秒对206毫秒,发行版中约57毫秒对97毫秒是最常见的运行值)。对于
公共字符串用户名{get;set;}
),与直接成员访问相比,性能开销是多少?(我知道这通常不会有什么不同,但在我的一些代码中,属性被访问了数百万次。)类TestTime1
{
公共TestTime1(){}
公共int id=0;
}
类TestTime2
{
公共TestTime2(){}
[默认值(0)]
公共int ID{get;set;}
}
班级计划
{
静态void Main(字符串[]参数)
{
尝试
{
TestTime1 time1=新的TestTime1();
TestTime2 time2=新的TestTime2();
秒表表1=新秒表();
秒表表2=新秒表();
watch2.Start();
对于(int i=0;i<10000000;i++)
{
time2.ID=i;
i=时间2.ID;
}
watch2.Stop();
watch1.Start();
对于(int i=0;i<10000000;i++)
{
time1.id=i;
i=时间1.id;
}
watch1.Stop();
WriteLine(“1和2的时间:{0},{1}”,watch1.elapsedmillesons,watch2.elapsedmillesons);
}
捕获(例外情况除外)
{
控制台写入线(例如消息);
}
Console.In.ReadLine();
}
}
它主要用于抽象(您可以稍后添加验证,而无需破坏现有代码或重新编译)
即使在使用自动属性时,编译器仍会生成一个支持字段,并将按此执行。完全不用担心性能开销。它太小了,你不应该考虑削弱类的封装;这将是最糟糕的过早优化 这仅仅是因为抽象性和模块性吗?是否还有其他过度驾驶的原因 据我所知并非如此;这些理由本身就足以令人信服。但也许会有其他人参与进来 编译器将属性访问转换为函数调用。对于没有备份存储的属性(例如,公共字符串UserName{get;set;}),与直接成员访问相比,性能开销是多少?(我知道这通常不会有什么不同,但在我的一些代码中,属性被访问了数百万次。) 在生成的中间语言中,属性访问被转换为方法调用。然而,正如这个词所说,这只是一种中间语言:它被及时编译成其他语言。这个转换步骤还涉及优化,比如简单属性访问器等普通方法的内联 我希望(但您需要进行测试以确保)抖动能够处理这样的访问器,因此不会有性能差异。1)这是为了封装原则,但其他.NET功能使用诸如数据绑定之类的属性 2) 我不确定我是否同意这一点,我一直听说,如果属性是直接获取/设置,那么它的速度与标准字段访问一样快——编译器会为您执行此操作
更新:似乎两者兼而有之,编译为方法调用,但JIT优化了。无论如何,这种性能问题都不会对代码产生有意义的影响。但是,请注意,关于实现属性的指导是使它们尽可能轻,调用方不希望它们昂贵。在我发布帖子后,我意识到它基本上是为了隐藏对象的内部工作。连续运行测试20次,确保在发布版本中启用JIT优化:
Time for 1 and 2 : 47,66
Time for 1 and 2 : 37,42
Time for 1 and 2 : 25,36
Time for 1 and 2 : 25,25
Time for 1 and 2 : 27,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 26,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
是的,JITter非常擅长内联属性访问器。性能不是问题,永远不应该考虑。我以前问过
我猜您使用的是VS2008,使用的是64位操作系统,并且将编译设置为“任意CPU”?如果是这样,x64 JIT编译器不会内联属性。它们在32位上运行,使它们在性能上与公共字段相同。确保使用Ctrl-F5而不是F5运行;否则,调试器仍将附加,即使在发布模式下,某些优化也可能无法正常工作。至少在我的机器上是这样的:F5给出的结果与您发布的结果相似,而Ctrl-F5给出的结果相同。如果您想要一个特定的示例,说明需要属性,但不能使用常规成员变量,请考虑继承:如果类使用公共成员,此类的派生无法实现验证或其他getter/setter行为。他们一直坚持使用变量,如果他们想做一些不同的事情,他们必须1)忽略现有成员变量并创建一个新属性,2)添加一个新属性,以及3)重写调用或依赖成员变量的每个方法以使用该属性。这不仅是不必要的更多工作,如果编写派生类的人没有访问源代码的权限,这几乎是不可能的 如果基类使用属性而不是成员变量,那么问题只是将验证或其他行为添加到get/set函数中,并且
Time for 1 and 2 : 47,66
Time for 1 and 2 : 37,42
Time for 1 and 2 : 25,36
Time for 1 and 2 : 25,25
Time for 1 and 2 : 27,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 26,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25