dotnet / dotnet/csharpstandard

Method group conversion rules could not be implemented

Open
#820 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C#
Stars
815
Forks
99
Avg merge
1d 14h
Merged PRs (30d)
16

Description

The [current rules](https://github.com/dotnet/csharpstandard/blob/draft-v7/standard/conversions.md#108-method-group-conversions) for "method group conversions" say that it should bind like a method invocation: "A single method M is selected corresponding to a method invocation of the form `E(A)`".

The [current rules](https://github.com/dotnet/csharpstandard/blob/draft-v7/standard/expressions.md#1251-general) for "member lookup" know to ignore non-invokable members when we're dealing with an invocation:
1. "If a member is a method or event, or if it is a constant, field or property of either a delegate type or the type dynamic (, then the member is said to be invocable."
2. "Next, if the member is invoked, all non-invocable members are removed from the set."

Those two rules cannot be implemented as-is, and the compiler does not in fact implement them.
The problem is that when binding a delegate conversion like `Action a = o.M;` we don't know that we're in a method group conversion until we've bound the right-hand side, but we can't bind the right-hand side without knowing whether we're being invoked or not.

Here are two scenarios to illustrate the problem. Per the spec, I would expect `System.Action a = c.M;` and `c.M()` to bind the same way, without error, in both of those scenarios. But in fact, only the invocation syntax `c.M()` binds successfully.

```
C c = null;
System.Action a = c.M; // error CS0029: Cannot implicitly convert type 'int' to 'System.Action'
c.M(); // okay

public class Base
{
public void M() { }
}

public class C : Base
{
public int M; // non-invokable field
}
```

```
C c = null;
System.Action a = c.M; // error CS0029: Cannot implicitly convert type 'int' to 'System.Action'
c.M(); // okay

public static class E
{
public static void M(this C c) { }
}

public class C
{
public int M; // non-invokable field
}
```

Tagging @MadsTorgersen @BillWagner @alekseyts @jjones

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.