- "Are you converting the topic?" "Yes, I'm explicitly converting it, so it's kinda dangerous"
Champion issue: #5497
Related: https://github.com/dotnet/csharplang/blob/1e8255a438517bc3ad067c726c28cfa20cb60f1e/meetings/working-groups/extensions/extensions-as-static-types.md
Today, we looked at a proposal for scoping the work involved in extensions to something more manageable for initial previews. Extensions being able to be used as types adds many complexities to the design, and by forbidding this, we may be able to get previews out sooner for earlier feedback. Extensions depend on this their typeness in two major cases:
- The type of
this
inside the extension - Their disambiguation syntax
The latter is something that we've had more general proposals around before, particularly around calling DIMs from implementing types. Such a syntax could serve us here as well, and if we go with the restriction, is something that we want to seriously investigate. While a majority of the LDM is ok with allowing extensions to ship without an explicit syntax for disambiguation, a plurality is not ok with this. We prefer to reach consensus, rather than simply doing majority rules, so we'll definitely be investigating this and bringing back results to the LDM for further discussion.
The type of this
is a bit harder, particularly if we ever want to re-expand back to allowing extension
s to be able to be local types. For example:
extension E for object
{
public void M()
{
Console.WriteLine(Identity(this));
string Identity<T>(T t) => typeof(T).Name;
}
}
If we change the type of this
at a later date, then this goes from printing object
to printing E
. While we may end up being ok with such a breaking change, we still need to
acknowledge that it is a breaking change.
Another part of making this
be the underlying type is that it means that, when shadowing a base type member, it's very difficult to call the shadowing member. Consider:
extension E for string
{
public int Length => 10;
public void M()
{
Console.WriteLine(this.Length); // This calls `string.Length`, not `E.Length`
}
}
We should consider warning in these scenarios, to let the user know that they're doing something that is almost certainly useless and not what they intended to do (or at the very least, likely will not work the way they expected it to).
Ultimately, we think we're ok with continuing to explore this restricted space. We want to be able to get previews out into our user's hands sooner rather than later, and this seems like a viable approach to managing the large complexity of the feature.
Restricting extension
s from being instance types is tentatively approved. We will also investigate disambiguation syntax for calling specific members, a more general feature than
just for extension
s.