Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update extensions_v2.md #8502

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions proposals/extensions_v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -397,5 +397,70 @@ Roles, on the other hand, seem more fitted to the type space where they are trul

This warrants deep discussion about the path taken here and the future we are envisioning, to ensure we're happy with any paths this current approach may close off or make more difficult.

# Alternate strawmen syntaxes
CyrusNajmabadi marked this conversation as resolved.
Show resolved Hide resolved

The above strawman chooses a big syntactic jump forward for all extension member cases. That's not at all a requirement, and many options are possible. A non-exhaustive list of variants are:
CyrusNajmabadi marked this conversation as resolved.
Show resolved Hide resolved

## Variant 1: Reuse existing syntax when possible

Instead of introducing `extension` or syntax for an instance-extension-method, we can reuse syntax. For example:

```c#
// Continue to use static-class
static class MyExtensions
{
// Continue using existing syntax for instance extension methods
public static void Boo<T>(this T value) { }

// New instance extensions would be simpler:
// Property form:
// No more 'val' to name the instance. You use 'this'. Same for the other instance members.
public int Count<X> for SomeType<X> { get { ... } }

// Static extension members are the same as above. They already do not name an 'instance'.
}
```

This has the benefit of not needing two syntaxes for instance method extensions. And reducing the amount of tweaks an extension member can make.
CyrusNajmabadi marked this conversation as resolved.
Show resolved Hide resolved

Pros: It's clear what this is reducing to. Merging ('partial') with existing static classes is clear. All the restrictions on static-classes stay the same and don't need to reapply to 'extensions'. No need for new syntax for extension-instance-methods.
Cons: Later augmentations like `static class MyExtensions for string` may or may not feel good. Extension instance methods and other members would not have a consistent syntactic augmentation.

## Variant 2: No generic non-method members.

The original proposal puts generics on all members, beyond just methods. However, this is not explicitly required, as this only adds capabilities to new extension members (extension methods already support generics). As such, we could require that any non-method extensions on generic-types themselves stay non-generic, with only the extension being generic. In other words:

```c#

extension E<T> for SomeType<X>
{
// Property form:
// Auto-properties, or usage of 'field' not allowed as extensions do not have instance state.
public int Count { get { ... } }

// Event form:
// Note: would have to be the add/remove form.
// field-backed events would not be possible as extensions do not have instance state.
public event Action E { add { } remove { } }

// Indexer form:
public int this[int index] { get { ... } }

// Operator form:
// note: no SomeType<X> val, an operator is static, so it is not passed an instance value.
public static SomeTypeX<X> operator+(SomeType<X> s1, SomeType<X> s2) for SomeType<X> { ... }

// Conversion form:
// note: no SomeType<X> val, an operator is static, so it is not passed an instance value.
public static implicit operator SomeTypeX<T>(int i) { ... }

// Constructor form:
// note: no SomeType<X> val, an operator is static, so it is not passed an instance value.
public SomeType() { }
}
```

CyrusNajmabadi marked this conversation as resolved.
Show resolved Hide resolved
Pros: No need to introduce non-method generic instance members.
Cons: Being able to add non-method instance members to generic types requires solving generic extensions.
## Detailed design
CyrusNajmabadi marked this conversation as resolved.
Show resolved Hide resolved
[design]: #detailed-design