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

Champion "ref extension methods on structs" (C# 7.2) #186

Open
4 of 5 tasks
gafter opened this issue Feb 26, 2017 · 7 comments
Open
4 of 5 tasks

Champion "ref extension methods on structs" (C# 7.2) #186

gafter opened this issue Feb 26, 2017 · 7 comments
Assignees
Labels
Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification Proposal champion Proposal
Milestone

Comments

@gafter
Copy link
Member

gafter commented Feb 26, 2017

See also dotnet/roslyn#165

@gafter gafter added this to the 7.2 candidate milestone Feb 26, 2017
@Thaina
Copy link

Thaina commented Feb 27, 2017

Very important feature

@benaadams
Copy link
Member

Precedent in VB.NET. Should be compatible? (Currently C# can't see VB.NET's byref extension methods)

Also should work with ref returns; which enables low cost fluent or functional struct apis

@orthoxerox
Copy link

See also #128 (ref operators (on structs))

@alrz
Copy link
Member

alrz commented Jun 22, 2017

What happens if we have two overloads,

void Deconstruct<T, U>(in this KeyValuePair<T, U> k, out T key, out U value) { .. }
void Deconstruct<T, U>(this KeyValuePair<T, U> k, out T key, out U value) { .. }

I think this should be possible to provide a ref variant without breaking existing code and the compiler should prefer the first overload afterwards.

@Thaina
Copy link

Thaina commented Jan 3, 2019

The reasons why we do not want to allow this on classes
It would break long standing invariant that a method call cannot turn non-null receiver to become null after invocation.
In fact, currently a non-null variable cannot become null unless explicitly assigned or passed by ref or out. That greatly aids readability or other forms of "can this be a null here" analysis.

I think it could be amend this case by having compiler enforce that, extension method must not assign a possible null value into the ref this argument

The ability to mutate reference type make it easy to write a lazy initializing or conditional caching

public static class Ext
{
    public void InitializeIfNull<T>(ref this T obj) where T : ICanInitial // some interface for initializing pattern
    {
        if(obj != null)
            return;

        // initialize obj by ICanInitial pattern
    }
}

public class SomeClass : ICanInitial
{
    public static DerivedSomeClass _instance;
    public static DerivedSomeClass Instance => _instance.InitializeIfNull();
}

And we must always check that it will not be null anytimes in that function

public static class Ext
{
    public T InitializeIfNull<T>(ref this T obj) where T : ICanInitial // some interface for initializing pattern
    {
        if(obj != null)
            return;

        obj = GetFromSomeWhere(); // ERROR it might be null
        if(GetFromSomeWhere() is var got && got != null)
            obj = got; // not null by flow analysis

        obj = GetFromSomeWhere() ?? obj; // should not error, it never change from object to null, worst case is null to null
    }
}

@333fred 333fred added the Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification label Oct 16, 2020
@TCROC
Copy link

TCROC commented Jan 29, 2021

Would it make sense to include this on extension methods for other immutable types like delegates as well?

@333fred
Copy link
Member

333fred commented Jan 29, 2021

If you want to propose that, I would suggest opening a new issue. This shipped a few years ago and is just waiting to be added to the ECMA spec.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification Proposal champion Proposal
Projects
None yet
Development

No branches or pull requests

8 participants