csharplang/meetings/2019/LDM-2019-07-17.md
2019-07-29 16:53:45 -07:00

3.7 KiB

C# LDM Notes for July 17, 2019

Agenda

  1. Nullability of events
  2. Triage

Discussion

Field-like events

This discussion was spurred by the current implementation, which treats field-like events as fields, meaning non-nullable unless annotated, and requiring initialization in the constructor if non-nullable.

Based on design decisions around our non-nullable field warnings and the current annotation implementation of events, we recognized a potential problem. For almost every event, the behavior would be nullable, but it seems laborious to require every event to be annotated with nullable, when that is the usage for almost every event.

It was also noted that field-like events also imply multiple pieces of generated code: a backing field, which can only be directly accessed in the containing type, and generated add/remove accessors that can be accessed everywhere. Notably, the nullability of the generated field must be compatible with, but not identical to to the generated accessors.

Possibilities:

  1. What you write is what you get
  • Both the event and field have the declared type, and if it's nonnullable, you're forced to initialize in the constructor
  1. The backing field is always nullable
  • Would not allow assigning an empty delegate in the constructor and then invoking without a null check
  1. Force implementing manually
  2. Use attributes, perhaps [MaybeNull]
  3. Events are always nullable
    • This is (2), but the += and -= are also nullable

Notably, the += and -= generated for field-like events is null safe, in that you can pass null as a delegate argument and it does not produce a null reference exception.

Even though it's painful, (1) seems to be attractive because it doesn't heavily special case events, and EventHandler? accurately reflects the nullability of the event, in that it allows nullable handlers to be subscribed, and invoking the event could cause a null reference exception. A problem is that unassigned non-null events as currently implemented produce a warning that complains about the event being unassigned, when in almost all situations the proper fix is to declare the event type as nullable.

(2) would match the usage of almost all fields, but at the expense of inconsistency, since we usually require ? to annotate nullable items, and events would be special-cased to be nullable by default. It would also disallow the pattern of assigning an empty delegate in the constructor.

Conclusion

For most users, making events nullable seems like the right behavior.

(5) would address this in the simplest way, but we really don't like the inconsistency of making types nullable without a '?'.

(1) allows events to be annotated as nullable, which is what we expect most people should do.

We're sticking with (1). Current behavior is confirmed.

Triage for the rest of the meeting

Support XML doc comments on local functions

It's especially frustrating that XML doc comments in local functions are an error. It also seems useful in larger methods where you want to see the contract for a local function in intellisense.

However, the second reason is also a good reason to allow XML doc comments for locals.

Conclusion

Interested, but we want to see what the possibilities are on other locals.

Warn on obsoleting overrides of non-obsolete members

It might be useful, but is low value. Since it would be a new warning, this is blocked on warning waves.

Conclusion

We will revisit when we get warning waves.

Proposals for ConfigureAwait with context

ConfigureAwait and related issues have been brought up many times. We think it's worth addressing, and should look at possible designs.

Conclusion

Let's look it for a future major release.