簡體   English   中英

C#派生類和基本構造函數參數邏輯

[英]C# derived class and base constructor parameter logic

我有一個基類:

public class Base
{
    public Base(X x ,Y y){
        this.x = x;
        this.y = y;
    }

    public X x{get;}
    public Y y{get;}
}

和一個派生者:

public class Derive : Base
{
    public Derive(Z z, Q q) :Base (? ?)
    {
    }

    private void ConstructXY(Z z, Q q)
    {
        //Advanced logic for creating an X and a Y
        if(q.something == 5){
            this.x = new X(28); 
        }
        else{
            this.x = new X(25);
        }

        if(this.x.something == 25 && q == 9){
            this.y = new Y(1);
        }
        else{
            this.y = new Y(5)
        }
    }
}

現在,如果沒有“高級”邏輯,就無法正確地調用基本構造函數。 我曾經能夠從Derive.ctor()調用ConstructXY()並從那里設置x和y,這不再有效,因為我刪除了x和y設置器。 我的現實生活場景包含更多邏輯,因此我不願意創建三元混亂。

如果適合靜態方法,則可以調用“高級”邏輯

這是使用C#7中可用的Tuple的方法:

public class Base
{
    // This constructor was added to avoid calling twice ConstructXY
    public Base((X x, Y y) tuple) :
        this (tuple.x, tuple.y)
    {

    }

    public Base(X x, Y y)
    {
        this.x = x;
        this.y = y;
    }

    public X x { get; }
    public Y y { get; }
}

public class Derive : Base
{
    public Derive(Z z, Q q) : base(ConstructXY(z, q))
    {
    }

    private static (X x, Y y) ConstructXY(Z z, Q q)
    {
        X x;
        Y y;

        //Advanced logic for creating an X and a Y
        if (q.something == 5)
        {
            x = new X(5);
        }
        else
        {
            x = new X(25);
        }

        if (x.something == 25 && q == 9)
        {
            y = new Y(1);
        }
        else
        {
            y = new Y(5)
        }

        return (x, y);
    }
}

如果您不能在基類中更改XY的訪問修飾符,以便子類可以訪問它們,那么您將必須遵守合同,將構造函數留在可以設置這些成員的唯一可能的位置。

添加更多邏輯來計算這些值的唯一方法是使用靜態方法,例如:

public class Derive : Base
{
    public Derive(Z z, Q q)
        : base(ConstructX(q), ConstructY(q, z))
    { }

    private static X ConstructX(Q q)
    {
        if (q.something == 5)
            return new X(28);
        else
            return new X(25);
    }

    private static Y ConstructY(Q q, Z z)
    {
        if (z.something == 25 && q.something == 9)
            return new Y(1);
        else
            return new Y(5);
    }
}

由於這些是單獨的方法調用,因此您無法“一次”計算兩個值,因此,如果不再次基於ZQ重新進行計算,就無法使Y的結果取決於X的結果。

解決此問題的另一種方法是,完全刪除Derive上的public構造函數,並提供一個靜態工廠方法:

public class Derive : Base
{
    private Derive(X x, Y y)
        : base(x, y)
    { }

    public static Derive Create(Z z, Q q)
    {
        // here you can use your original logic to calculate X and Y
        X x = …
        Y y = …

        return new Derive(x, y);
    }
}

根據您的計算復雜度,這可能是更好的解決方案。 如果確實需要原始的ZQ值,則只需擴展private構造函數以同時使用它們並存儲它們:

private Derive(Z z, Q q, X x, Y y)
    : base(x, y)
{
    this.Z = z;
    this.Q = q;
}

為什么不將您的基類設置器聲明為私有:

public class Base
{
    public Base(X x ,Y y){
        this.x = x;
        this.y = y;
    }

    public X x{get; private set;}
    public Y y{get; private set;}
}

這樣,您仍然可以在構造函數中設置它們,並且它們將無法在外部設置?

我不太喜歡這種方式,如果可能的話會避免使用,但是您可以在對base的調用中使用三元語句:

public Derive(Z z, Q q)
    : base(new X(xCondition ? 28 : 25), new Y(yCondition ? 1 : 5))

使用靜態方法進行轉換。 像這樣。

public class Derive : Base
{
    public Derive(Z z, Q q) :base (ConvertToX(z, q), ConvertToY(z, q))
    {
    }

    private static X ConvertToX(Z z, Q q) {
        if(q.something == 5){
            return new X(28); 
        }
        return new X(25);
    }

    private static Y ConvertToY(Z z, Q q) {
        // TODO
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM