簡體   English   中英

構造函數鏈接或使用命名/可選參數

[英]Constructor chaining or use named/optional parameters

我是一個非常新的程序員,並且了解我們希望最大限度地減少代碼冗余,因此當我們更新時,我們可以進行盡可能少的更改並最大限度地減少錯誤。

所以我有一個 Student 類,我想要重載構造函數,所以如果我做反向鏈接,它就像這樣。

 public class Student
{
    string name;
    int Id;

    public Student()
    {
    }
    public Student(string name)
    {
        this.name = name;
    }
    public Student(string name, int Id) :this(name)
    {
        this.Id = Id;

但這顯然很糟糕,因為我們出於什么原因想要在一個構造函數中包含所有代碼? 閱讀方便嗎?

    public Student() : this(null, 0)
    { }
    public Student(string name) : this(name, 0)
    { }
    public Student(string name, int Id) 
    {
        this.name = name;
        this.Id = Id;
    }

如果我做這個前向鏈接,那么如果我們添加一個像 string major 這樣的新字段會發生什么? 如果我進行前向鏈接,那么我會使用添加的字段創建一個新的重載構造函數。 但是現在我必須更改所有其他構造函數以調用新的構造函數。 如果我進行反向鏈接,我只是創建一個新的構造函數並調用前一個重載的構造函數。

    public Student(string name, int Id, string major):this(name, Id)
    {
        this.major=major;
    } 

這似乎更好地遵循 OOP,但是我教科書中的所有示例都顯示了前向鏈接,並且沒有說明為什么我不應該使用后向鏈接。

如果我使用命名/可選參數,那就更容易了。

    public Student(string name = null, int Id = 0, string major = null)
    {
        this.name = name;
        this.Id = Id;
        this.major = major;
    }

如果我需要另一個字段,我只需要編輯唯一的構造函數。 這似乎最好地遵循 OOP 原則還是我錯了? 它至少可以最大程度地消除代碼重復。 我的任務是“按照 OOP 的原則實施學生課程”。 我知道所有這些都是有效的,但這是編碼構造函數的最佳/公認方式之一嗎? 我缺少的命名/可選參數是否存在缺陷? 作為初學者,有很多方法可以對此進行編碼,這非常令人困惑。

沒有最好的方法,因為它們是不同的,它們每個都有優點和缺點。

從 C# 1.0 開始就可以使用獨立構造函數和鏈式構造函數,大多數情況下我們使用鏈式構造函數,但有時如果兩個構造函數要處理的事情完全不同,我們必須使用前者。

class Student
{
    public Student()
    {
        DoSomething();
    }

    public Student(string name)
    {
        this.Name = name;
        DoAnotherThing();
    }
}

與可選參數構造函數相比,上面兩個要長得多,但說實話,它們更安全。 考慮以下情況:

public class Student
{
    public Student(string firstName = null, string lastName = null)
    {
        this.FirstName = firstName;
        this.LastName = lastName;
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
}

//it's working fine
//var danny = new Student("danny", "chen");

//as the business grows a lot of students need a middle name
public Student(string firstName = null, string middleName = null, string lastName = null)
{
    this.FirstName = firstName;
    this.MiddleName = middleName;
    this.LastName = lastName;
}

//for a better sequence the programmer adds middleName between the existing two, bang!

它們之間的另一個區別是使用反射。 可選參數不會為您生成更多構造函數,如果您使用反射調用構造函數,則不會應用默認值。

我知道所有這些都是有效的,但這是編碼構造函數的最佳/公認方式之一嗎?

據我所知,不是 - 你有很多選擇。 您的同事是達成共識的最佳人選。 C# 正在成為一種非常豐富的語言,這意味着將有許多不同的方法來實現同一件事。

我缺少的命名/可選參數是否存在缺陷?

據我所知,不是。 我個人認為這是最好的解決方案,但其他人可能會有所不同。

作為初學者,有很多方法可以對此進行編碼,這非常令人困惑。

歡迎編程。 我們有數以百萬計的程序員,我們都在忙着給世界增加復雜性!

我建議更深入地了解這個假設:

“但這顯然很糟糕,因為我們出於什么原因希望在一個構造函數中包含所有代碼”

Fluent Interface Pattern將這些東西分開,我也不能強烈認為這直接轉換為構造函數。

customer
    .NameOfCustomer("Shiv")
    .Bornon("12/3/1075")
    .StaysAt("Mumbai");

說明性實施:

public class Customer
{
    public string FullName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Address { get; set; }

    public Customer NameOfCustomer(string name)
    {
        this.FullName = name;
        return this;
    }

    public Customer BornOn(DateTime dateOfBirth)
    {
        this.DateOfBirth = dateOfBirth;
        return this;
    }

    public Customer StaysAt(string address)
    {
        this.Address = address;
        return this;
    }
} 

示例源

這是部分答案。 您的“向后鏈接”,一個構造函數設置一些參數,然后為其余的調用另一個構造函數,對於普通函數來說是非常合理/明智的:一個函數完成部分工作,然后調用另一個函數進行其他工作,並且等等。

但是對於公共構造函數,它們中的任何一個都可以被客戶端代碼調用,期望得到一個完全構造的對象,完全初始化。 您示例中的某些構造函數未初始化成員(除非您想要的是該類型的默認值)。

作為替代方案,您可以擁有私有構造函數。

暫無
暫無

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

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