过去,在C和C ++版本中,如果在紧密循环中执行,嵌套指针解除引用被认为是一个相对昂贵的操作。
你不想被抓住:
for (int i = 0; i < 10000000; i++)
{
j->k->l->m->n->o->p->dosomeworknowthatwereherewhynoteh();
}
因为你可能会失去宝贵的毫秒数。 (是的,我有点讽刺!)
迁移到.NET的世界......
这是否更贵
System.Runtime.InteropServices.Marshal.WriteInt32(Abort, 1)
比这个?
Imports System.Runtime.InteropServices.Marshal
.
.
.
WriteInt32(Abort, 1)
答案 0 :(得分:26)
这是苹果和橘子的比较。
System.Runtime.InteropServices.Marshal.WriteInt32(Abort, 1)
与C ++中的相同:
Foo::Bar::Baz::Func(a, b);
换句话说,编译器将命名空间折叠成零成本。
为了获得相同的东西,你可能会有这样的东西:
public class Foo {
public Person Agent { get; }
}
Foo f = getFooFromWhereEver();
f.Agent.Name.ToString().ToLower();
在这种情况下,假设Person有一个名为Name的属性,它是一个字符串。在这种情况下,点链进行四次方法调用,其中至少有一种是虚拟的,但更可能不是所有这些都是不变的,因此多次调用它们是多余的。我说“更有可能......”因为这取决于Agent和Person的实现。
答案 1 :(得分:9)
命名空间中的点数并不昂贵;它们在编译时由编译器解析,而不是在运行时解析。 (实际上它是相反的,挑剔;如果使用using / imports语句来缩短代码,类型引用将扩展到完整的类型名称,包括命名空间,在编译时) 。但是,达到属性或方法的点确实有成本。
这两个应该具有相同的性能:
System.Collections.Generic.List<string> myList = new System.Collections.Generic.List<string>();
// using System.Collections.Generic
List<string> myList = new List<string>();
虽然重复访问属性的属性可能会花费:
for (int i = 0; i < 100000; i++)
{
int n = this.ActiveControl.Size.Width;
}
// this should be faster
int width = this.ActiveControl.Size.Width;
for (int i = 0; i < 100000; i++)
{
int n = width;
}
答案 2 :(得分:5)
在您的示例情况下使用导入,没有区别。 imports语句只是确保您不必每次都输入完整路径。
但是,如果你写了:
for(i=0; i<10000; i++)
{
classInstance.memberclass.memberclass.memberclass.memberclass.writeInt32(bla);
}
然后是的,写作可能会更好:
SomeClass someclass = classInstance.memberclass.memberclass.memberclass.memberclass;
for(i=0; i<10000; i++)
{
someClass.writeInt32(bla);
}
答案 3 :(得分:4)
它由编译器解决,因此性能完全相同。
答案 4 :(得分:1)
实际上,在你的两个案例中,我都希望结果是平等的。
在C示例中,您实际上是在运行时查看对象并将其解除引用,因此人们认为这是一项昂贵的操作并不奇怪。但是在C#示例中,您正在讨论的“点”在编译时是静态解析的。
答案 5 :(得分:0)
我在博客上写了一篇详细的文章,我也有一个基于微秒的计算,但是当你加起来时,你肯定会有所不同。
http://akashkava.com/blog/?p=95
然而,我的文章做了各种计算,它也计算了namedvaluecollection和属性访问时间等。但了解一切如何运作会很有用。