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
gafter opened this issue Feb 26, 2017 · 5 comments
Open

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

gafter opened this issue Feb 26, 2017 · 5 comments

Comments

@gafter
Copy link
Member

@gafter 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 Thaina commented Feb 27, 2017

Very important feature

@benaadams
Copy link
Member

@benaadams benaadams commented Feb 27, 2017

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

@orthoxerox orthoxerox commented Mar 16, 2017

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

@alrz
Copy link
Contributor

@alrz 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 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
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants
You can’t perform that action at this time.