# 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: ```C# 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.