Skip to content

Latest commit

 

History

History
145 lines (99 loc) · 4.34 KB

LDM-2019-02-27.md

File metadata and controls

145 lines (99 loc) · 4.34 KB

C# Language Design Meeting for Feb. 27, 2019

Agenda

  1. Allow ObsoleteAttribute on property accessors
  2. More Default Interface Member questions

Discussion

Allow ObsoleteAttribute on property accessors

ObsoleteAttribute, ConditionalAttribute, and CLSCompliantAttribute are currently disallowed on property accessors. VB allows the first three, but provides a warning for ClSCompliant.

The question is whether or not to loosen this restriction.

Allowing Conditional seems very dangerous because the "arguments" to the method are not evaluated if the condition is false. Logically, this would imply that the right-hand side in a property assignment expression is not evaluated, but this seems very likely to lead to bugs and confusion.

We don't see a reason to disallow Obsolete or Deprecated, and don't particularly care about CLSCompliant.

Conclusion

Allow the change for Obsolete and Deprecated. Leave everything else as-is.

Collision of lookup rules and decisions for base()

Example:

interface I1
{ 
    void M(int) { }
}

interface I2
{
    void M(short) { }
}

interface I3
{
    override void I1.M(int) { }
}

interface I4 : I3
{
    void M2()
    {
        base(I3).M(0) // What does this do?
    }
}

The tricky part here is that both M(short) and M(int) are applicable to M(0), but lookup rules also say that if we find an applicable member in a more derived interface, we ignore members from the less derived interfaces. Combined with the rule that overrides are not found during lookup, when looking in I3 the first thing we find is I2.M, which is applicable, meaning that I1.M does not appear in the list of applicable members.

Since we concluded in the previous meeting that an implementation must exist in the target type, and I2.M is the only applicable member, the call base(I3).M(0) as written is an error, because I2.M does not have an implementation in I3.

Conclusion

The decision from the previous meeting is affirmed and we conclude that the lookup rules will not be changed. It's not clear what the new lookup rules would be and it would be difficult to find when to apply them. In general, we think having a single set of lookup rules will reduce confusion in an already complicated feature area.

Semantics of base(T).Member

We also affirm that for base(T).Member:

  • T can be a class or interface
  • All members are available on base(T).Member including fields
  • A definition or implementation must exist in T

Aside: The compiler will never emit a call to a member in metadata that is inaccessible.

This decision essentially falls out of existing binding rules for the given expression.

Accessibility in interfaces

We previously agreed to support at least protected, private, and public.

What about internal, protected internal, or private protected?

In addition, what is the meaning of protected?

Conclusion

Allow all accessibility. protected specifically seems useful for compatibility with other languages which allow it, and to allow interfaces to create helper methods for their derived implementations.

There are seem to be two possible definitions of protected: protected members are visible only in deriving interfaces, or protected members are visible in both deriving interfaces and implementing classes.

The preferred definition is protected members being visible in all deriving interfaces and implementing classes.

Accessibility of overriding interface members

There are two issues here: what is the language rule around calling overriding implementations via base and how to implement that rule via accessibility in the CLR.

We like the rule that you should always be able to call an overriding implementation through base() as long as you can see the definition.

The problem is that the obvious implementation (copying the accessibility of the definition) doesn't quite work with InternalsVisibleTo (which is technically not described in the language).

Proposal 1:

If the implementing member is in the same assembly as the definition we can copy the accessibility.

Proposal 2:

For all explicit interface implementations, emit the protected accessibility.

Conclusion

The language rule is confirmed.

We think Proposal 2 works with the language rules, is simple, and doesn't expose anything that we would regret. Let's go with that.