我一直在读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个参数,这看起来不太干净,是否有更好的方法来创建不可变的类?或者也许我花了太多的心思而不应该为此担心。
答案 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