如果该类采用许多参数,最干净的方法是什么?

时间:2018-10-18 20:22:26

标签: c#

我一直在读Clean Code这本书,它说函数参数不应超过2,而对于使用我的函数的任何人来说,这都比这更令人困惑。我的问题是,这如何适用于不可变的类?举例来说,我有以下内容:

public class Song
{
    private readonly string name;
    private readonly double price;
    private readonly string owner;
    private readonly int id;

    public string Name{get{return name;}}
    public double Price{get{return price;}}
    public string Owner{get{return owner;}}
    public int Id{get{return id;}}

    public Song(string name, double price, string owner, int id)
    {
        this.name = name;
        this.price = price;
        this.owner = owner;
        this.id = id;
    }
}

我的构造函数中有4个参数,这看起来不太干净,是否有更好的方法来创建不可变的类?或者也许我花了太多的心思而不应该为此担心。

2 个答案:

答案 0 :(得分:0)

鲍勃叔叔建议,理想情况下,函数(方法)应该没有参数。但是,如果有必要,除非有充分的理由要求第三,否则将它们控制在两个以下。超过三个是代码气味。

其背后的原因是您的函数应该小而简单。这使它们易于阅读和理解(即“干净”)。如果您有三个以上的参数,则该方法最有可能做不止一件事情。将其拆分为单独的方法。

话虽这么说,我认为他关于限制参数数量的建议不适用于类构造函数。除了initialize fields or properties之外,构造函数不应该真正

  

构造函数与类或结构具有相同的名称,并且它们通常会初始化新对象的数据成员

简单地初始化字段/属性没有太多的复杂性。我会说您的代码仍然“干净”。

编辑:正如Eric Lippert在评论中指出的那样,您可以使用auto-implemented properties来简化代码:

public class Song
{
    public string Name { get; }
    public decimal Price { get; }
    public string Owner { get; }
    public int Id { get; }

    public Song(string name, decimal price, string owner, int id)
    {
        this.Name = name;
        this.Price = price;
        this.Owner = owner;
        this.Id = id;
    }
}

答案 1 :(得分:0)

您需要在不可变类的构造函数中传递参数。因此,如果您的课程很长,那么会有很多参数。如果感觉更干净,则可以创建一个复制构造函数,但是传入的实例将再次需要使用冗长的构造函数定义,传入每个参数以映射到实例字段或属性。我们至少也可以使用C#6.0只读属性来压缩代码。在Linqpad中输入以下代码,您将看到Linqpad通知我们无法将歌曲从“ Thunderstruck”设置为“ Big Gun”,因为我们已将该属性声明为只读。更少的仪式,更少的代码,这就是我们想要的。也许我们可以对表达式树做一些优雅的事情,甚至可以进一步压缩代码?至少这是我的建议。

void Main()
{
    var song = new Song("Thunderstruck", 15, "AC/DC Records",
        123
    ); 
    var songAwesome = new Song(song);
    songAwesome.Name.Dump();
    songAwesome.Name = "Big Gun"; //This line fails because the property is redonly

}

public class Song
{

    public string Name { get; } //readonly props in C# 6.0
    public double Price { get;}
    public string Owner { get; }
    public int Id { get; }

    public Song(Song song) : this(song.Name, song.Price, 
    song.Owner, song.Id){

    } //Let us have a copy constructor just for the fun of it

    public Song(string name, double price, string owner, int id)
    {
        this.Name = name;
        this.Price = price;
        this.Owner = owner;
        this.Id = id;
    }
}


// Define other methods and classes here