-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Please allow to define static local variables in functions, like C/C++ #10552
Comments
Static local variables are a way of maintaining state between calls to the same function. They are needed in C. They aren't needed in either C++ (though they exist there because of the origins of that language) or C#. You can achieve the same maintenance of state either through fields in object instances, or with static fields in a class. |
@DavidArno |
public void Foo() => PrivateFoo.Foo();
private static class PrivateFoo
{
private static int CallTimes;
public static void Foo() =>
Console.WriteLine($"Function Foo has been called {++CallTimes} times");
} Of course, just because the language already supports such a construct, doesn't mean one should ever write code like this... |
@DavidArno: How is that more readable than public void Foo()
{
static int callTimes = 0;
Console.WriteLine($"Function Foo has been called {++callTimes} times");
} The more interesting question is whether there would be one |
I'm not saying it's more readable. I'm saying that this functionality can already be achieved with the language, as is. Since it wraps global static state within a single, very hard to mock, function, it's a pretty nasty implementation of the singleton anti-pattern. Changes to the language should enhance it. Simplifying the syntax around an already-implementable anti-pattern isn't my idea of enhancing a language. |
Note that VB.NET has always had this feature, it was inherited from VB5/6: Public Sub Bar()
Static CallTimes As Integer
CallTimes += 1
Console.WriteLine($"This method was called {CallTimes} times.")
End Sub Just pointing that out. I'm not endorsing the feature. I'm personally not a fan of hiding shared state in the middle of a function like that. I considered it bad practice back when I was writing VB5/6. |
It should be noted that there are not too many differences between C and C++ in this area. In C++, static data members can have same storage duration category (static or thread-local) with namespace scope or block scope variables, the only differences are scoping (which has an effect on locality of names, i.e. information hiding), and (vs. block scope ones) the time of initialization. I'm not a fan of this feature but it is strange to allow static fields while disallowing static local variables, since the latter actually always does better than the former in several cases due to the differences above. Note the style to return a reference to a local static variable (delayed initialization, only when needed) is a variant of so-called monostate pattern, which is not quite the same to singleton pattern, but a better replacement in many cases, esp. since C++11, the initialization can be thread-safe easily, while the traditional singleton is still having a lot of problems (and very hard to do right) in C++, Java, C#, so on. |
@FrankHB +1 |
Duplicate of #49 |
Perl's public static class Blah {
private static void Foo() {
System.Func<int> fn = () => {
static int a = 0;
return a++;
};
System.Console.Write("{0} {1} {2}", fn(), fn(), fn());
}
public static void Bar() {
Foo();
Foo();
}
}
|
@DerpMcDerp But also unnecessary given that you can just define |
@HaloFour Except that defining |
@DerpMcDerp Considering how frequently such a problem is encountered and necessarily solved (read: never) I'd say that the few extra lines of code necessary to manage lazy initialization is a very small price to pay. The net effect is identical anyway. |
@DerpMcDerp You are effectively overloading the |
Your example isn't quite the same thing as VB's static...Not to mention creating a static class to hold a single value seems like too much work, most people are simply going to make it a regular instance field and leave a comment saying it should only be used in X and hope that is well enough. Particularly since the value that you are creating is truly static (life time of the app) while VB's is scoped to a particular INSTANCE of a class and it's lifetime.
|
In the past it seems like the main arguments against adding this could all be applied to local functions as well, so now that they are included I would vote yes (obviously in C# 8 at this point) if there were formal voting. |
I'd use static locals with recursion, but now local functions are included I can handle such use cases with them within the scope of each instance. But there could be cases where shared access among instances is needed, so it's a +1 for me (specially given that it's already present in VB). |
Why is it still allowed to close issues without comment? |
@NetMage GitHub allows users to close their own issues. We can only set policy regarding the action of a subset of those users. 😄 |
That would seem to be a problem - I open an issue, it is closed as Duplicate of someone else's issue. They close that issue and my interest in the issue is effectively lost. |
@NetMage If this issue is of interest to you, I would recommend filing on dotnet/csharplang, since that's where proposals for changes to the language are getting filed now. I searched but didn't see a duplicate (doesn't mean one doesn't exist). |
Follow-up discussion: dotnet/csharplang#832 |
I don't quite understand how the original discussion evolved. Having local static variables is merely a syntactic sugar. void MyFunc() { } can be easily processed to an already supported pattern void MyFunc() { I don't understand what's with the anti-pattern concerns mentioned above. The feature would offer a cognitive and organizational benefits by making sure a specific class field is accessible only to the function that declared it. Initialization and readonly modifier are not a concern, because this is only a syntactic sugar that guarantees a variable won't be used elsewhere (the field is strongly coupled with a function). The point of guaranteeing uniqueness is to prevent clashes when two functions locally declare static variables which bear the same name. I need to reiterate once more how strongly this affects the readability of a code that is vastly more complex than this example. |
@syndrome this issue was closed 7 years ago. Please use the existing discussions on dotnet/csharplang for your thoughts. Thanks. |
The static local variables can only be used in the functions which define them. C/C++ have this feature.
For example:
The text was updated successfully, but these errors were encountered: