Search code examples
c#lambdaconstructortuplesdeconstructor

What composition of rules make the constructor public Point (double x, double y) => (X, Y) = (x, y) valid?


The constructor public Point (double x, double y) => (X, Y) = (x, y); is obviously valid. But what composition of rules makes it so? It's obviously some combo of tuples, lambdas, and deconstructors, but I don't know exactly what step appears where. For example, I don't know if (X, Y) is where it is for a tuple trick or for a lambda trick. Is it possible to break this constructor's inner workings down in to very small steps, such that the exact rules that make it work can be made obvious?


Solution

  • As suggested by @CodeCaster in their comment to your original post, expression-bodied members and tuple deconstruction are the keywords here.


    Your constructor

    public Point(double x, double y) => (X, Y) = (x, y);
    

    is implemented as an expression-bodied member, which consists of member, => and expression, as follows:

    public Point(double x, double y) => (X, Y) = (x, y);
    --------------------------------    ----------------
                 member                    expression
    

    The expression-bodied member implementation is a shorthand version of this:

    public Point(double x, double y)
    {
        (X, Y) = (x, y);
    }
    

    The constructor's body

    (X, Y) = (x, y);
    

    is implemented by using tuple deconstruction to assign the value for properties X and Y.

    The deconstruction can be visualized as follows:

    (    X     ,     Y    ) = (  x    ,   y   )
     ---------   ---------     ------   ------
     variableA   variableB     valueA   valueB
    

    Hence, the constructor body

    (X, Y) = (x, y);
    

    could be implemented as follows:

    X = x;
    Y = y;
    

    To summarize, your constructor implementation is basically equal to the following:

    public Point(double x, double y)
    {
        X = x;
        Y = y;
    }
    

    As mentioned in my original comment, it may be easier to see that (X, Y) = (x, y) belongs to what you call the 'tuple trick' part by extracting (X, Y) = (x, y) into a method and calling that method in the constructor:

    public Point(double x, double y) => SetPoint(x, y);
    

    , where SetPoint() has several possible implementations:

    private void SetPoint(double x, double y) => (X, Y) = (x, y);
    
    private void SetPoint(double x, double y)
    {
        (X, Y) = (x, y);
    }
    
    private void SetPoint(double x, double y)
    {
        X = x;
        Y = y;
    }