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: support "type of the current object" as declared return type. #2494

Open
biqas opened this issue Feb 8, 2015 · 10 comments
Open

Proposal: support "type of the current object" as declared return type. #2494

biqas opened this issue Feb 8, 2015 · 10 comments

Comments

@biqas
Copy link

biqas commented Feb 8, 2015

public class Self
{
    public this Self1()
    {
        // Only allowed to return with keyword this.
        // Very important that only 'this' is allowed as returning value.
        return this;
    }

    public this Self2()
    {
        // NOT allowed.
        return new Self();
    }

    public this Self3()
    {
        // NOT allowed.
        return new Object();
    }
}
@jmarolf
Copy link

jmarolf commented Feb 8, 2015

Could you give an example of how this would be useful? Unless I am misunderstanding, don't constructors fill this role today?

@manish
Copy link

manish commented Feb 8, 2015

What would be other significant use of this syntax apart from method chaining?

@biqas
Copy link
Author

biqas commented Feb 8, 2015

Maybe this one is giving more examples:
http://roslyn.codeplex.com/discussions/562656

@biqas
Copy link
Author

biqas commented Feb 8, 2015

@manish
that you can type safe method chain of same reference or derived ones!

@gafter gafter changed the title Proposal: Allow to return keyword "this" Proposal: support "type of the current object" as declared return type. Feb 9, 2015
@SolalPirelli
Copy link

Duplicate of #155, I think. An equivalent of Scala's this.type would be welcome indeed.

@McZosch
Copy link

McZosch commented Feb 10, 2015

The idea is pretty simple, I guess.

If you have a immutable base class A and a derived class B, and modifications are made through members in class A, those members always return A. If you want to apply the same modifications to type B without having to do a lot of casts, you need to overload any method within B.

So, the method definition needs to say [type of this], i.e. return [A] when instance is typed [A] and [B] when instance is typed [B].

Two problems:

First, if the method is only implemented in class A, it would need to be implemented type-agnostic to handle all thinkable derived types. It will quickly become a System.Activator.CreateInstance-party, with the compiler handling several variance issues. A performance nightmare coupled with unnecessary complexity.

Second, this feature is already delivered through extensions and type-constraints. This spreads your code over two classes, which is problematic for some coding styles. Maybe, we should be capable of using static class members as extensions.

@biqas
Copy link
Author

biqas commented Feb 10, 2015

@McZosch
Extension methods can't be overridden.

@gafter
Returning "type of the current object" is semantically different to returning "this" reference.

public class BaseClass
{
    public virtual this Foo()
    {
        return this;
    }
}

public class DerivedClass1 : BaseClass
{
    public override this Foo()
    {
        return this;
    }
}

public class DerivedClass2 : BaseClass
{
    public override this Foo()
    {
        // Is a valid call, because the "this" reference is returned.
        return base.Foo();
    }
}

Co-variant return types have different semantic.

class Compilation ...
{
    virtual Compilation WithOptions(Options options)
    {
        // the proposal is not allowing new object creation.
        return new Compilation();
    }
}
class CSharpCompilation1 : Compilation
{
    override CSharpCompilation1 WithOptions(Options options)
    {
        // the proposal is expecting CSharpCompilation as return type.
        return new CSharpCompilation1();
    }
}
class CSharpCompilation2 : CSharpCompilation1
{
    override CSharpCompilation1 WithOptions(Options options)
    {
        // the proposal is expecting CSharpCompilation2 as return type.
        return base.WithOptions(options);
    }
}

@jcouv jcouv self-assigned this Sep 1, 2016
@Thaina
Copy link

Thaina commented Sep 23, 2016

Well... after some times I think we could just workaround with generic extension method

public class OurStringBuilder
{
    internal void Append();
}

public class OurStringBuilderExt
{
    public S Put<S>(this S sb,string s) where S : OurStringBuilder
    {
        sb.Append(s);
        return sb;
    }

    public S AppendLine<S>(this S sb,string s) where S : OurStringBuilder
    {
        sb.Append(s);
        sb.Append(Environment.NewLine);
        return sb;
    }
}

new OurStringBuilder().Put("s").Put("t").Put("r").Put("i").Put("n").AppendLine("g");

This is satisfied our need. It also work with interface on struct and everything. Also we could implement most logic in extension method instead of its base class

@jcouv jcouv removed their assignment Dec 8, 2016
@gafter gafter transferred this issue from dotnet/roslyn May 6, 2019
@Shadowblitz16
Copy link

Shadowblitz16 commented Oct 30, 2020

What about returning a variable types?

Note this is not the way I would do it but its just a example..

    public class Node : I 
    {
        internal Node       _parent;
        internal List<Node> _children = new List<Node>();

        public _parent.GetType() GetParent()
        {
            return _parent;
        }
        public _children[n].GetType() GetChild(int n)
        {
            return _children[n]
        }

Returning this only works if the method is in the current class

@biqas
Copy link
Author

biqas commented Oct 30, 2020

@Shadowblitz16
this would defeate the purpose of the proposal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants