Using R# for 2 days - some things are annoying

1. Auto-complete behavior is changed. You start typing "private" and there is no more automatic drop down list with selection. You have to press Ctrl-Space now, why??? what was wron with the standard VS way?

2. Right click a method name. What is the great idea behind changing the standard VS context menu item text "Find All References" with "Find Usages"?!

3. Right click a method name. What is the great idea behind changing the standard VS context menu item text "Go to Definition" with "Go to Declaration" when in fact in C# you can not have a method declaration separated from its definition.

4. Why do you think by default R# should suggest convert
byte[] a = new byte[10]
to "Implicitly Typed Local Variables" like
var a = new byte[10]
Do you think it's a good idea to use Implicitly Typed Local Variables everywhere? Read MS comments on that, the main idea was to use it in LINQ to avoid having data holder types.

5. Code sample:

DateTime d;
while(true)
{
d = Foo();
if (d < DateTime.Now)
break;
}

Why do you think it's a good idea to move declaration of "d" inside the while loop? Do you think it's more effective allocating DateTime structure on stack gazilion of times?

17 comments

I'll guess you're not a native English speaker, which is why you don't realise how rude you come across in this post.

Your issue 4 has been repeatedly discussed here - personally I also think R# gets the default wrong, but it's extremely easy to change this to a 'hint' from the alt-enter context menu, at which point you won't be bothered by it again.

I guess in Issue 5 you don't mean 'allocated on the stack', because that's meaningless in that there is no such thing as an 'allocation on the stack' operation which occurs at run-time. Perhaps you're actually concerned about the constructor of DateTime being called repeatedly? I'd have to see a more elaborate example than the one you posted, because the compiler compiles out the temporary variable altogether in the fragment you posted, and even when one adds extra code to keep the temporary variable present, what the compiler actually generates is directly equivalent to the code R# is suggesting. (Indeed, Reflector decompiles your 'optimised' code as the code R# is trying to suggest)

0

RE: #5 - It is never a good idea to try and preoptimize code based on trying to guess which way the compiler is going generate the IL. In fact, the C# compiler allocates all variables at the start of the method, so R# suggests defining the variable close to it's use for readability.

I found the ReSharper team is really on top of these issues and they usually have a really good reason for suggesting a change or implementing a feature. Give them the benefit of the doubt and look into their docs.

Edited by: Jeffrey Odell on Aug 28, 2008 6:04 AM

0

To Jeffrey Odell:
"It is never a good idea to try and preoptimize code based on trying to guess which way the compiler is going generate the IL."
-Good idea! May I suggest c# language spec as a primary source so you don't have to guess anymore?
"In fact, the C# compiler allocates all variables at the start of the method."
-WRONG! C# allocates local variables when program flow ENTERS THEIR DECLARATION SCOPE. Here is how you can check it:
void Foo()
{
int x = 0;
for (int i = 0; i < 10; i++)
{
DateTime t;
}
}
set a break point at 'x' declaration and run code. When stopped at it do you see in the "Locals" window variable 't'? No! Any idea why? ...Right, because flow ahsn't entered the 't' declaration scope yet!
Keep going and step into 'for' loop - as soon as for statement condition is determined to be true the program flow enters 't' declaration SCOPE - the 'for' loop body, and it gets allocated and you can see it in the debugger window!
Keep going - when program gets back to checking 'for' operator condition stop here... where is our 't'?! It's gone, deallocated.

0

As for #4 it's ok for me, I can change it. But we have team members who are new to C# and they may take this suggestion as a rule and.. I don't even want to think of that nightmare.

#5: This is exactly what I mean - local variables are allocated on stack, others on heap. And yes, both occur exactly at run time. Want proof? Read my reply to Jeffrey Odell and try the sample code below (I guess). I think you won't need more elaborate example after you find out about locals allocation or will be able to come up with your own. For instance think of local var of structure type where your structure has 100 fields and all of them would have to be allocated over and over again.

0

Since DateTime is a value type, it is extremely unlikely that moving it into a loop will have any impact on performance. If you can provide an example where there is a measurable change in performance, please post it.

In general, the RS suggestion is correct as it provides for cleaner code, and since the DateTime value is only used inside the loop it is better to limit the scope of the variable to the inside of the loop.

0

As a follow-up, here is the dissambly of Foo, from which you can see that the allocation takes place outside the loop, and that as written the only code (outside for loop execution) in the loop is a couple of NOPs.

static void Foo ( )
{
00000000 push ebp
00000001 mov ebp,esp
00000003 push edi
00000004 push esi
00000005 push ebx
00000006 sub esp,40h
00000009 lea edi,[ebp-48h]
0000000c mov ecx,0Fh
00000011 xor eax,eax
00000013 rep stos dword ptr es:[edi]
00000015 xor eax,eax
00000017 mov dword ptr ,eax
0000001a cmp dword ptr ds:[00929134h],0
00000021 je 00000028
00000023 call 76AB8EF1
00000028 xor edx,edx
0000002a mov dword ptr ,edx
0000002d mov dword ptr ,0
00000034 xor edx,edx
00000036 mov dword ptr ,edx
00000039 nop
int x = 0;
0000003a xor edx,edx
0000003c mov dword ptr ,edx
for ( int i = 0; i < 10; i++ )
0000003f xor edx,edx
00000041 mov dword ptr ,edx
00000044 nop
00000045 jmp 0000004C
{
00000047 nop
DateTime t;
}
00000048 nop
for ( int i = 0; i < 10; i++ )
00000049 inc dword ptr
0000004c cmp dword ptr ,0Ah
00000050 setl al
00000053 movzx eax,al
00000056 mov dword ptr ,eax
00000059 cmp dword ptr ,0
0000005d jne 00000047
}

0

I prefer use of var whever possible, so I am fine with #4.

As to your hypothetical use of a structure with 100 fields, unless you want the structure to retain information about previous iterations, it is going to have to be initialized every time inside the loop. This would be in addition to the initialization done, if as you prefer, the declaration is placed outside the loop. Again as a structure the allocation of space is trivial, and the cost to initialize will be more important (depending on what default and initialization code is involved). If you are using the values from the structure outside the loop, then I doubt RS would suggest declaring it inside the loop. So unless you can come with a concrete example, I don't see any merit to your objection #5.

0

Exactly the point I was trying to make. If you compile the code he likes, and then decompile it (back to C#) with Reflector, what you actually get is the code he DIDN'T like.

He seems confused about what 'allocation on the stack' actually entails too, and between lifetime and lexical scope.

0

Will,

The most likely thing is that Rodion has solid C++ background. If the code
was written in C++ every loop iteration would eventually start with DateTime
allocation on a stack and its constructor call unless there was a really
smart optimization pass in the compiler.

--
Sergey V. Coox
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"


0

I guess you're right. The allocation takes place outside a loop and only once. Can you point me to the place in spec where it is described please?


also when playing with that I discovered that this code does not compile:

int x;
{
int x;
}

But according to the spec the outer x should just get hidden by inner x when entering the block where inner x is declared. It compiles in C++ though.

Ok, it takes #5 out of my list )
But the other 4 stay, especially #1. I'll try version 5, but if the auto-complete feature is still screwed up... Thank you, but no thanks.

0

Hello Rodion,

Please verify you have enabled autopopup intellisense after letters and digits
in ReSharper / Options / Environment / IntelliSense / Completion Behavior.

Sincerely,
Ilya Ryzhenkov

JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"


IR> I guess you're right. The allocation takes place outside a loop and
IR> only once. Can you point me to the place in spec where it is
IR> described please?
IR>
IR> also when playing with that I discovered that this code does not
IR> compile:
IR>
IR> int x;
IR> {
IR> int x;
IR> }
IR> But according to the spec the outer x should just get hidden by
IR> inner x when entering the block where inner x is declared. It
IR> compiles in C++ though.
IR>
IR> Ok, it takes #5 out of my list )
IR> But the other 4 stay, especially #1. I'll try version 5, but if the
IR> auto-complete feature is still screwed up... Thank you, but no
IR> thanks.


0

Tthe debugger is showing you the variables that are in scope at the time of the breakpoint. I would not infer anything about allocation from that.

Premature optimization - trading code clarity for guesses as to what the compiler will do - is usually thought of as "not a good idea". You may feel differently, which is why ReSharper lets you customize whether or not you want it to offer that hint. You can turn it off and go happily on your way.

Hey - I was just trying to explain what the ReSharper team was thinking - not looking for a SHOUTING DEBATE :>

0

Ilya,
there really is a problem with the default behaviour for intellisense. It behaves differently from VS "out of the box". Only after you go to Options => Intellisense => Completion Behaviour and check all checkboxes there, it behaves like VS's intellisense. But until new user's discover this option, they might already have uninstalled R# because they think it "messed up" intellisense. So it might well be that, if you change the default settings here to behave like VS intellisense, you might dramatically increase your sales :)

Regards,
Urs

0

Exactly. But even if you change the settings the colors in that drop down list is for some sort of aliens - blue font on dark blue background. Is there a way to disable that "invention" completely?

0

Could it be that they improved that "blue on blue" color scheme in one of the last daily builds? since I rembered this was a problem, but in the current daily build it seems to be gone. I have white letters on blue background on my system.

0

blue on blue applies to the part of word you've already typed, the rest is white on blue

0

Hello Urs,

We fixed defaults in one of the recent builds of 4.1.

Sincerely,
Ilya Ryzhenkov

JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"


IR> Ilya,
IR> there really is a problem with the default behaviour for
IR> intellisense. It behaves differently from VS "out of the box". Only
IR> after you go to Options => Intellisense => Completion Behaviour and
IR> check all checkboxes there, it behaves like VS's intellisense. But
IR> until new user's discover this option, they might already have
IR> uninstalled R# because they think it "messed up" intellisense. So it
IR> might well be that, if you change the default settings here to
IR> behave like VS intellisense, you might dramatically increase your
IR> sales :)
IR> Regards,
IR> Urs


0

Please sign in to leave a comment.