繁体   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