Skip to content
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

Issue: C# Assigning variable to inline delegate and using it in the delegate body causes "Using unassigned variable" error #15660

Closed
pmunin opened this issue Dec 4, 2016 · 5 comments

Comments

@pmunin
Copy link

pmunin commented Dec 4, 2016

Expected Behavior:

Action<Node, Action<Node> > traverseTree = (node, visitNode)=>
{
     visitNode(node);
     node.Children.ForEach(c=>traverseTree(c, visitNode)); //Compiler throws "Using of unassigned variable 'traverseTree'"
}

Actual Behavior:

Action<Node, Action<Node> > traverseTree = null;
traverseTree = (node, visitNode)=>
{
     visitNode(node);
     node.Children.ForEach(c=>traverseTree(c, visitNode));
}

Another good use case which is very common provided by @jnm2:

SomeDelegate oneTimeHandler = null;
obj.SomeEvent += oneTimeHandler = (s, e) =>
{
    obj.SomeEvent -= oneTimeHandler;
    // ...
};

And combined with #15659 it could be something like this:

obj.SomeEvent += var oneTimeHandler = (s, e) =>
{
    obj.SomeEvent -= oneTimeHandler;
    // ...
};

@pmunin pmunin changed the title Issue: C# Using inline delegate variable in the delegate body causes "Using unassigned variable" error Issue: C# Assigning variable to inline delegate and using it in the delegate body causes "Using unassigned variable" error Dec 4, 2016
@HaloFour
Copy link

HaloFour commented Dec 4, 2016

That is expected behavior. The variable has not been assigned yet. This applies to any expressions that attempt to reference the variable before it has been assigned, even if that variable will be assigned as a result of the expression:

int x = x + 1; // CS0165: Use of unassigned local variable 'x'

For delegates specifically, local functions alleviate the need for this as their hoisted scope allows them to be self-referential.

@pmunin
Copy link
Author

pmunin commented Dec 4, 2016

int x = x+1; is different, because variable is used by execution flow before it was assigned.
In case of assigning to a delegate - its body execution is deferred and will happen obviously when the variable assignment is accomplished.

@HaloFour
Copy link

HaloFour commented Dec 4, 2016

The compiler does not track the lambda body as separate from the body of the current method, particularly in the case of a closure. In any case this feature is addressed by local functions which are being added to C#.

@pmunin
Copy link
Author

pmunin commented Dec 27, 2016

Just found out how this feature is implemented in F#:

let rec fact x =
    if x < 1 then 1
    else x * fact (x - 1)

@CyrusNajmabadi
Copy link
Member

Closing this out. We're doing all language design now at dotnet/csharplang. If you're still interested in this idea let us know and we can migrate this over to a discussion in that repo. Thanks!

Note: this is doable with local-functions, and that woudl be the recommended approach here.

@CyrusNajmabadi CyrusNajmabadi closed this as not planned Won't fix, can't repro, duplicate, stale Nov 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants