5

I've been working in C for the past couple of years and I've managed to get use to putting single-purpose, static variables near where they are used within my code.

While writing a very basic method that was in need of a method-scope static value, I was a bit surprised to find that the compiler didn't like that I tried to define a static object from within my method.

Googling has verified that this isn't possible within C#. Still, I'm curious why code, like the following, is completely off limits.

public int incrementCounterAndReturn()
{
    static int i = 0;
    return ++i;
}

Granted, this is a simplistic example that could be redefined for the same affect but that's beside the point. Method-scope, static values have their place and purpose. What design decisions have prevented such an implementation of static objects within C#?

We're on C# version 5.0 and it's 2013. I can only assume this isn't possible because of a design choice and not just because "that's complex and hard stuff to implement." Does anyone have any insider information?

svick
  • 236,525
  • 50
  • 385
  • 514
RLH
  • 15,230
  • 22
  • 98
  • 182
  • "Possible duplicate" : http://stackoverflow.com/questions/10795502/what-is-the-use-of-static-variable-in-cwhen-to-use-itwhy-cant-i-declare-the-s –  Jul 31 '13 at 17:53
  • I'm not aware of any stated reason why they didn't implement this in C#. I would personally consider it bad practice, at least for the use cases I'm thinking of. – JosephHirn Jul 31 '13 at 18:08
  • 3
    Just write this code in VB.NET. And look at the generated IL. Yes, it is *that* expensive to ensure that the variable is only initialized once when more than one thread can call this method. Hiding a ton of code is not the C# way. Not the VB.NET way either but they didn't have the choice. And not the C way, it just lets you shoot your leg off. – Hans Passant Jul 31 '13 at 18:17
  • Thanks @HansPassant. I should have considered that! – RLH Jul 31 '13 at 18:18
  • A related, more popular feature request: [Property backing value scope](http://stackoverflow.com/q/12098745/18192) . – Brian Jul 31 '13 at 18:56

5 Answers5

9

The language design team is not required to provide a reason to not implement a feature. Rather, the person who wants the feature is required to make the case that the feature is the best possible way the design, implementation, test, and education teams can be spending their budgets. No one has ever successfully done so for your proposed feature.

Were I still on the design team and had this feature pitched I would point out that it is completely unnecessary. The feature in C is a known cause of developer confusion, particularly for novices, and the benefit of local vs type scope is tiny.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Thanks Eric! You're right, there is no requirement to say why you haven't implemented something into a language. Still, I was curious whether or not this was decided as a specific choice as something to avoid doing, or if it was something that wasn't done because it would have been a lot of work, with little (to no) benefit. Again, thanks. This is what I was looking for. – RLH Jul 31 '13 at 18:21
  • I've added some text to address your comment. – Eric Lippert Jul 31 '13 at 18:24
3

The underlying runtime does not provide method level static variables. In the CLR, all "static" data is defined on the type level, not method level. C# decided to not add this at the language level in its language design.

This is purely a design choice. VB.Net, which compiles to the same IL, does allow this via the Shared keyword in a Function or Sub statement (though it's handled via the compiler "promoting" the variable to a class level static variable).

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 1
    I'm c# mostly, but curious as to how VB handles this. What does VB copmpiler do if you declare two static method level variables in different methods with the same name? Alias them ? Do you have to access them with `TypeName.Alias` ?? Or are they only accessible from within the method ? – Charles Bretana Jul 31 '13 at 17:54
  • 1
    @CharlesBretana It mangles the name of the variables, similar to what happens with the backing store for auto-properties in C#. The "real" name (as far as the CLR is concerned) is not what the user types in. – Reed Copsey Jul 31 '13 at 17:55
  • I had forgotten about the `Shared` keyword (it's been a long time since I've written any form of VB.) I understand how statics work in C#. Still, if you wanted to implement this, I think it could be done. I don't think it would be easy but, as I stated, I don't think it should be SO difficult that in over 10 years of .Net, it's never been added as a feature. I guess there haven't been enough pitchforks... – RLH Jul 31 '13 at 17:55
  • @Reed, And then I imagine you cannot access them from the Type name, only from within the method they are declared in, using the user-specified name ? – Charles Bretana Jul 31 '13 at 17:56
  • 3
    @RLH It could easily be added, if the language team felt it was warranted. Its just easy to work around (via declaring at the class level yourself), so there's little/no point in doing so. – Reed Copsey Jul 31 '13 at 17:56
  • @CharlesBretana Yes - they're only accessible within that method, and not elsewhere in the class. (You could, of course, use reflection to "find" and get at the variable, since it's really a private class level static in the runtime...) – Reed Copsey Jul 31 '13 at 17:57
  • 1
    @RLH Check out Eric Lippert's answer here: http://stackoverflow.com/a/2806990/65358 It's relevant as to "why this isn't done" (for any C# feature) – Reed Copsey Jul 31 '13 at 17:58
  • Yes, what I would like is for something like the VB implementation that ReedCopsey is talking about. Part of the reason why you may want a method scope, static variable is so that you cany use a very generic name for the field (like `i`) and not worry how it affects the rest of your code. Yes, class scope statics can still be used. Still, a method-scope is still useful. I wouldn't care if the compiler used some form of magic, promoting my method-static, to a class-static, and the method declaration being simple "syntactic sugar". Code-wise, the affect would be the same. – RLH Jul 31 '13 at 18:01
  • @RLH It's about a different feature - but that's how the language team approaches adding features in general. Method level statics are a similar thing -they have some nice use cases, but they also introduce a lot of complexity (how do you determine when they're initialized? They are going to be static level data underneath, but the initialization rules get odd), and it's easy to work around. – Reed Copsey Jul 31 '13 at 18:03
  • Thanks for all of these details Reed. I'll probably end up giving this the answer mark, except I think I'll let this one float for a while, just in case an MS insider decides to come in and elaborate further on the complexity issues or specific reasons on why it was explicitly designed out of the specification. – RLH Jul 31 '13 at 18:16
1

static variables are scoped to the class, not to an object instance. To make this work, your method must be declared static, and I believe your class must also be static (since instantiation is not relevant).

But the variable itself must be declared at the class level. C# doesn't allow you to create method-local static variables.

Worth noting: these kinds of maneuvers make it very difficult to unit test the method properly. Normally in C# one would make an ordinary class to hold such state; in fact, that's exactly how yield return works behind the scenes.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
  • I'm not in front of my code right now, but are you saying that if I define a method as `static` I can also define a `static int` within the method? Interesting. – RLH Jul 31 '13 at 17:54
  • 1
    @RLH No, you can't - you still need to make the static variable class level. – Reed Copsey Jul 31 '13 at 17:54
  • @RLH: No, I was wrong; I just tried it and the IDE wouldn't accept it. `static` variable declarations must be done at the class level. – Robert Harvey Jul 31 '13 at 17:57
1

Because in the CLR, static variables are associated with the TYPE. Storage for them is tied to the Type (class or stuct) they are associated with.

Charles Bretana
  • 143,358
  • 22
  • 150
  • 216
  • While this is true, the language could work around it easily enough if the designers decided to do so. VB does, for example. – Reed Copsey Jul 31 '13 at 17:53
1

The .NET framework and languages were designed around the concept that anyone who is going to be compiling an assembly should be considered trustworthy enough to have access to all the code therein. From a semantic point of view, declaring a static variable foo within method bar would be equivalent to declaring a private static variable outside the method and accessing it within the method, provided only that one chooses as a name something which isn't used anywhere else. If one by convention combines the method name and meaning (e.g. bar_foo) one can generally avoid naming collisions pretty easily. Since the semantics are equivalent to having the variable declared outside the method, there's no need to have it declared inside.

supercat
  • 77,689
  • 9
  • 166
  • 211