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

Overload resolution for GetEnumerator fails with optional parameters #19742

Open
jskeet opened this issue May 24, 2017 · 2 comments
Open

Overload resolution for GetEnumerator fails with optional parameters #19742

jskeet opened this issue May 24, 2017 · 2 comments

Comments

@jskeet
Copy link

jskeet commented May 24, 2017

(Originally reported in ECMA standardization; copied here at the suggestion of @MadsTorgersen as it may somewhat fall out of async enumerable work.)

When iterating over a type that has a custom GetEnumerator method, it is claimed that after looking up the method group, the next step (in the C# 5 spec section 8.8.4) is to:

  • Perform overload resolution using the resulting method group and an empty argument list. If overload resolution results in no applicable methods, results in an ambiguity, or results in a single best method but that method is either static or not public, check for an enumerable interface as described below. It is recommended that a warning be issued if overload resolution produces anything except an unambiguous public instance method or no applicable methods.

However, that appears not to quite be the case:

using System;
using System.Collections.Generic;

class Test
{
    static void Main(string[] args)
    {
        foreach(var x in new Test()) // error CS1579: foreach statement cannot operate on variables of type 'Test' because 'Test' does not contain a public definition for 'GetEnumerator'
        {
            Console.WriteLine(x);
        }
    }

    public IEnumerator<int> GetEnumerator(int count = 10)
    {
        for (int i = 0; i < count; i++)
        {
            yield return i;
        }
    }
}

Here overload resolution with an empty argument list should be fine - I can call new Test().GetEnumerator(). There isn't an empty parameter list, but that's not the same thing.

(The same problem occurs for params int[] values, so we've actually had an issue since C# 1.0!)

@jcouv
Copy link
Member

jcouv commented May 25, 2017

Thanks for reporting this.
Let me do a bar check with the compat council. Since this has been working for a long time and it is not harmful, it may just become a grandfathered compiler bug. (see update in next comment)

As a side note, this reminds me of how the Deconstruct method is found. There it seems we are stricter (see DeconstructMethodHasParams2, OutParamsDisallowed, and DeconstructMethodHasArglist2).
It may be good to try GetEnumerator with __arglist as well...

@jcouv
Copy link
Member

jcouv commented May 25, 2017

Ah, I'd misunderstood the bug report. The current behavior is this code fails to compile (I edited the description to include the compiler error), but you would expect it to succeed.

@gafter gafter modified the milestones: 16.0, 15.6 May 26, 2017
@gafter gafter added the Bug label May 26, 2017
@jcouv jcouv modified the milestones: 15.5, 15.later Sep 29, 2017
@jcouv jcouv modified the milestones: 15.6, Unknown Nov 24, 2017
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