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

Discussion: async/iterator local function captures #11585

Closed
alrz opened this issue May 26, 2016 · 6 comments
Closed

Discussion: async/iterator local function captures #11585

alrz opened this issue May 26, 2016 · 6 comments

Comments

@alrz
Copy link
Contributor

alrz commented May 26, 2016

A common use case for local functions is to avoid state machine creation in async or iterator functions before parameter validation, etc. But if you capture any variable or parameter, the corresponding fields will be added to a class that we were intended to avoid creating in the first place. The only workaround is to pass every parameter to the local function which has to have a different name.

It would be nice to generate a separate struct for captured variables in async/iterator local functions, or permit a local function to shadow outer function's parameters.

Related: #11308

@gafter
Copy link
Member

gafter commented May 27, 2016

@ljw1004 You may be interested in this.

@svick
Copy link
Contributor

svick commented May 28, 2016

A simple struct wouldn't work, because the local function might modify a captured variable, which is then read by the parent method. Though this is probably not the common use case, so I think some optimizations regarding the closure allocation would be worthwhile.

@alrz
Copy link
Contributor Author

alrz commented May 28, 2016

@svick Note that this only happens when your local function is async or iterator; otherwise a struct will be passed by ref. So this is probably due to the fact that async/iterator functions cannot accept refs as parameter. Anyhow, the use case you've mentioned is 1% of the time, really, I'd never capture locals in a local function and then mutate them, that'd be a messy code, indeed. Since local functions cannot have something like capture lists, this can be a source of bugs. Currently, the best you can do is this: (even I'd like to get warnings if I accidentally capture any variables here, however it can be done via an analyzer),

public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
    if (source == null) ...
    if (predicate == null) ...
    IEnumerable<T> WhereImpl(IEnumerable<T> _source, Func<T, bool> _predicate) {
        foreach (var item in _source) {
            if (_predicate(item))
                yield return item;
        }
    }
    return WhereImpl(source, predicate);
}

Since this will be a common use case (capturing variables at callsite via parameters) I think it'd be nice to be able to use same parameter names as the outer function for the local one.

@alrz
Copy link
Contributor Author

alrz commented Aug 31, 2016

@gafter Can I reword this issue as a feature request to allow local function's parameters to shadow the outer method's parameter names, or is that a no-go?

@gafter
Copy link
Member

gafter commented Dec 9, 2016

@alrz I think repurposing this issue would be confusing. Please create a fresh feature request and include the motivating example(s).

@gafter gafter closed this as completed Dec 9, 2016
@alrz
Copy link
Contributor Author

alrz commented Dec 9, 2016

@gafter Right on. It's filed over at #15793.

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

3 participants