【发布时间】:2020-01-16 17:33:41
【问题描述】:
我有以下课程,想知道使用私有 setter 将 ListOfItems 声明为 public 是否正确(从 OOP 最佳实践的角度来看)。
public abstract class Game
{
public List<int> ListOfItemss { get; private set; }
protected Game()
{
}
protected Game(string gameInput)
{
ListOfItems = new List<int>();
var gameParser = new GameParser();
ListOfItems = gameParser.ParseGameInputString(gameInput);
}
public abstract int Bowl(int items);
}
或者我应该通过私有字段,即
public abstract class Game
{
private List<int> _listOfItems;
public List<int> ListOfItemss
{
get { return _listOfItems; }
private set { _listOfItems = value; }
}
protected Game()
{
}
protected Game(string gameInput)
{
ListOfItems = new List<int>();
_listOfItems = new List<int>();
var gameParser = new GameParser();
_listOfItems = gameParser.ParseGameInputString(gameInput);
}
public abstract int Bowl(int items);
}
-
-
根据建议更新: 根据以下建议,这是我认为最终版本中的代码:
public abstract class Game
{
public IReadOnlyCollection<int> ListOfItems { get; } = new List<int>();
protected Game()
{
}
protected Game(string gameInput)
{
var gameParser = new GameParser();
ListOfItems = gameParser.ParseGameInputString(gameInput);
}
public abstract int Bowl(int items);
}
【问题讨论】:
-
两者是一样的——唯一的区别是你在第二个实例中控制私有字段。您应该实现其中一个 - 好处是,如果您将其实现为属性而不是字段(这是上述方法之一),您可以调整属性的实现而不会破坏其他代码/重构。
-
仅供参考,当您立即将其设置为其他内容时,您无需将其设置为新列表。在第二个中更糟糕的是,您在将其设置为最终值之前将其设置为两个新列表。
-
是的,正如发布的答案所说 - 如果您希望分配在构造函数中并且它永远不会在代码中的其他任何地方,您可以通过删除设置器将其设为只读。您仍然可以将项目添加到列表中,只是无法分配新列表。
-
不,这就是我和 RufusL 的重点。
-
然后返回
ReadOnlyCollection<int>而不是List<int>将是要走的路。理想情况下,您应该将该属性声明为IReadOnlyList<int>。