-
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
Allow local variables to be static and/or readonly (deeper scoping) #49
Comments
Love this idea 👍 My ten cents on how to somewhat simplify the idea so that the problems of eager/lazy initialization hopefully go away is to just restrict the semantics of the declaration to mean that it is a private instance/static field on the class, but lexically scoped only to the method. This makes the hoist completely trivial - just give it an "unpronounceable" name - and the compiler rewrites references to it with the new name in the method. It also solves the initialization problem as the semantics are the same with any other instance/static field. If there is an initializer, the restrictions on it are the same as for regular initializers, and it is run at the same time as other instance/static initializers. If there isn't an initializer for non-readonly fields, it's up to the method to do any necessary initialization and locking etc. if thread safety is required. Alternatively, constructors could be allowed to set the field via MethodName.fieldname = blah; , much like they can for get-only auto-props now, although this falls apart when more than one overload uses an identically named method-local field :/ If the developer wants lazy semantics for the field - it's just the same as with a "normal" field, declare it as type Lazy, and refer to field.Value in the method. Multi-threaded scenarios are also explicitly not handled, as is the case with normal fields. I think all this fulfils the principle of least astonishment better as the syntactic sugar is incredibly thin, and it means that we get better scoping without having to worry about some complicated codegen going on underneath (which could change assumptions about things like memory use/locality etc.) |
💡 If you are going to allow |
For |
Don't we then reintroduce the problem of making it harder for the developer to know easily at a glance when the field is going to be initialized? And what if I explicitly don't want the lazy semantics? |
Other than constants that are literally replaced at compile time (as all constants are, but these wouldn't have a field), if static scoped fields are to added, why not instance fields? @matwilko, I agree with @sharwell. It makes a lot more sense to expect the field to be initialized on the first execution of the method. After all, it's where it's declared on the source. If you want/need it to be initialized elsewhere, than it's not logically scoped to the method. |
On a silly note, if this feature is introduced as |
@shunsukeaida VB.NET already has Implementing For var x = 1;
let y = 2;
x = 3; // legal
y = 4; // compiler error, y is readonly |
I know of VB's But yeah, the third example is what VB's |
@paulomorgado Fair enough :) Was just trying to simplify it down enough to avoid needing the debate on how and when to initialize the field when it's an instance field (the static case was always going to be pretty simple) The use of a Lazy to get the lazy-initialization for instance fields just feels a bit heavy to me, it adds a layer of indirection, (potentially) reduces locality, and requires a delegate to be instantiated, which all seems a bit much for what should be a lightning fast and memory-efficient field access. We could add manual locking with only an extra bool and object (to act as initialization check and locking object)? This keeps the field local to the object in memory, requires minimal extra memory to be used, and only results in one extra allocation. |
Proposal
Allow local variables (within method blocks) to be marked as
static
,readonly
, orstatic readonly
.Purpose
This would allow a developer to have the advantage of static and readonly fields, but limit their usage to a fine-grained scope.
Example:
This would help alleviate situations such as reallocating a new array (and assigning the value to fibonaccis) upon each execution of Method():
Or, it could help avoid potential issues with static field being accessible outside of its intended scope, purposefully or accidentally:
Implementation
The Roslyn compiler could recognize the syntax and generate the necessary IL code, just as it does for automatic properties, async/await, foreach, etc.
Originally, the discussion from codeplex talked about the potential issues and confusion, and the final thought I had was to lift the local variable as a
Lazy<T>
and for this feature to be purely syntactic sugar. After researching how VB.NET implements local static variables, the compiler does a bit more work to generate the correct IL code. See this article: http://weblogs.asp.net/psteele/7717. I think the same thought should be put into C#.While the article only talks about static local variables, I think that there would be real value to also allow the readonly keyword to be used as well. The complexity would grow, of course, because we have four possible situations (instead of just two):
The text was updated successfully, but these errors were encountered: