views:

330

answers:

7

In the past, in C and C++ land, nested pointer dereferencing was considered, by some, to be a relatively expensive operation if executed in a tight loop.

You wouldn't want to get caught with:


for (int i = 0; i < 10000000; i++)
{
  j->k->l->m->n->o->p->dosomeworknowthatwereherewhynoteh();
}

because you might lose precious milliseconds. (Yes, I'm being somewhat sarcastic!)

Moving to the world of .NET...

Is this more expensive


System.Runtime.InteropServices.Marshal.WriteInt32(Abort, 1)

than this?


Imports System.Runtime.InteropServices.Marshal
.
.
.
WriteInt32(Abort, 1)
+5  A: 

Dots in namespaces are not expensive; they are resolved by the compiler at compile time, not at runtime. (Actually it's the other way around, to be picky; if you use using/imports statements to shorten the code, the type references will be expanded to the full type name, including namespace, at compile time). Dots for reaching properties or methods do have a cost, though.

These two should have the same performance:

System.Collections.Generic.List<string> myList = new System.Collections.Generic.List<string>();
// using System.Collections.Generic
List<string> myList = new List<string>();

While accessing property of a property of a property repeatedly may cost:

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;
}
Fredrik Mörk
+4  A: 

It's resolved by the compiler, so performance is identical.

Joe
+23  A: 

This is an apples and orange comparison.

System.Runtime.InteropServices.Marshal.WriteInt32(Abort, 1)

is equivalent to this in C++:

Foo::Bar::Baz::Func(a, b);

In other words, namespaces fold up into zero cost by the compiler.

To get something that is equivalent, you might have something like this:

public class Foo {
    public Person Agent { get; }
}

Foo f = getFooFromWhereEver();
f.Agent.Name.ToString().ToLower();

In this case, imagine that Person has a property called Name which is a string. In this case, the chain of dots does four method invocations, at least one of which is virtual, but more likely than not all of these are invariant so calling them multiple times is redundant. I say 'more likely...' because that depends on the implementation of Agent and Person.

plinth
You're right apples and oranges but I needed an example to prove a pointer to co-worker. Thanks.
Added in a more appropriate comparison.
plinth
+1  A: 

It shouldn't be because it doesn't make any difference to what the runtime does.

The second form is just shorthand for the first

RobV
+4  A: 

in your example case with the imports, there is no difference. The imports statement just makes sure you don't have to type in the complete path everytime.

however, if you had written:

 for(i=0; i<10000; i++)
 {
      classInstance.memberclass.memberclass.memberclass.memberclass.writeInt32(bla);
 }

then yes it would probably have been better to write:

 SomeClass someclass = classInstance.memberclass.memberclass.memberclass.memberclass;
 for(i=0; i<10000; i++)
 {
      someClass.writeInt32(bla);
 }
Toad
+1  A: 

Actually, in both of your two cases I'd expect the results to be equal.

In the C example, you're actually looking at an object at runtime and dereferencing it, so it's not surprising that people consider it an expensive operation. But in the C# example, the "dots" you're talking about are resolved statically, at compile time.

John Feminella
A: 

I wrote a detailed articles on my blog and I also have a calculations based on microseconds but yes when you add up all, you can certainly make out difference.

http://akashkava.com/blog/?p=95

However my article does various calculations, it also calculates namedvaluecollection and property access time etc as well. But it can be useful to understand how everything works.

Akash Kava
I think -ve point markers should definately put some comments and show their face. I appriciate honesty and feedback.
Akash Kava