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

Proposal: Allow ref extension methods for unconstrained generic types #7696

Open
1 of 4 tasks
agocke opened this issue Nov 16, 2023 · 0 comments
Open
1 of 4 tasks

Proposal: Allow ref extension methods for unconstrained generic types #7696

agocke opened this issue Nov 16, 2023 · 0 comments
Assignees

Comments

@agocke
Copy link
Member

agocke commented Nov 16, 2023

  • Proposed
  • Prototype: Not Started
  • Implementation: Not Started
  • Specification: Not Started

Summary

The following code produces an error in C#:

public static class SExt
{
    static void SetVal<T>(this ref T @this)
        where T : IVal
    {
       ...
    }
}

Specifically, the error,

error CS8337: The first parameter of a 'ref' extension method 'SetVal' must be a value type or a generic type constrained to struct.

I propose removing the error for unconstrained generic parameters.

Motivation

The original motivation was to prevent people from writing somewhat shady extension methods that manipulated the receiver reference when the receiver is a reference type. This is a fine goal. But it's impeding a legitimate use case, which is providing an abstract API that works for both struct and reference type receivers, and appropriately propagates mutations. In these cases the caller will also have an unconstrained generic so they will not be able to determine whether they have a reference type or a value type, and thus not be able to satisfy the extension method struct constraint.

Detailed design

Remove the error for unconstrained generics.

Drawbacks

As mentioned, it could allow for some shady extension methods, although somewhat fewer since we still wouldn't permit known-reference types.

Alternatives

Something similar could maybe be done using static virtual methods. One of the main problems with using default interface methods for this purpose is that struct receivers are always boxed. In theory we could allow someone to write something like,

interface IVal
{
    static virtual void Set<T>(this ref T @this)
        where T : IVal
    {
        @this.DoWork();
    }

    void DoWork();
}

Note the this keyword in the parameter list of Set<T>. This could theoretically serve a similar purpose to the extension method -- it would provide a non-boxing default interface implementation.

Unresolved questions

N/A

Design meetings

@agocke agocke self-assigned this Dec 6, 2024
@dotnet dotnet locked as resolved and limited conversation to collaborators Dec 6, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

1 participant