dotnet / dotnet/csharpstandard
8.7.2.3 Hiding through inheritance
- Dominant language
- C#
- Stars
- 815
- Forks
- 99
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 16
Description
In 9.7.2.3 we have
> A method introduced in a class or struct hides all non-method base class members with the same name and all base class methods with the same signature (§9.6).
However, there is nothing in the name lookup rules making hidden methods inaccessible, or preventing them from being found during name lookup.
In 13.5.1 (Member lookup) it says
> - Next, members that are hidden by other members are removed from the set. For every member S.M in the set, where Sis the type in which the member M is declared, the following rules are applied:
> - If M is a constant, field, property, event, or enumeration member, then all members declared in a base type of S are removed from the set.
> - If M is a type declaration, then all non-types declared in a base type of S are removed from the set, and all type declarations with the same number of type parameters as M declared in a base type of S are removed from the set.
> - If M is a method, then all non-method members declared in a base type of S are removed from the set.
Note that there is no reference to signature comparisons in the name lookup rules. There is also the apparently non-normative commentary
> For member lookups in types other than type parameters and interfaces, and member lookups in
interfaces that are strictly single-inheritance (each interface in the inheritance chain has exactly zero or
one direct base interface), the effect of the lookup rules is simply that derived members hide base
members with the same name _or signature_. Such single-inheritance lookups are never ambiguous.
The "or signature" appears to have been added, and I believe it has been added incorrectly. The name lookup rules have no reference to anything from 16.3.4 (Inheritance) about method hiding by a method with the same signature:
> - A derived class can ***hide*** (§9.7.2.3) inherited members by declaring new members with the same name or signature. Note however that hiding an inherited member does not remove that member—it merely makes that member inaccessible directly through the derived class.
This is apparently commentary, as there are no normative rules making a hidden method actually inaccessible, or preventing it from being found during name lookup, or mandating any kind of error for its use.
The Roslyn compiler accepts the following program, and I cannot find anything in the specification that disagrees with the compiler:
``` c#
class C1
{
internal void M(int i = 0) { }
}
class C2 : C1
{
new void M(int i) { } // hide C1.M
void Entry()
{
M(); // invokes C1.M
}
}
```
See also https://github.com/dotnet/roslyn/issues/18486 where some poor compiler engineer is hopelessly confused by the fact that the specification defines hidden members, and then uses a completely different definition for the same term during name lookup.
Contributor guide
Research direction
Compare sections 8.7.2.3, 13.5.1, and 16.3.4, then review the linked Roslyn issue and the example in this report. Determine whether the normative lookup rules should address signature-based hiding and align with the commentary. Done means the standard consistently defines hidden-member lookup and the example's behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- compilers
- Issue type
- Documentation
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100