用这种方式修改List是不好的做法?

时间:2012-05-22 20:40:53

标签: c#

在A类中(如果列表不为空,将输出什么内容):

private List<int> _myList = new List<int>
public List<int> MyList {get{return _myList;} set{_myList = value;}}

在B组:

public bool MyClassBMethod(stuff)
{
     //stuff
     try{
          something
     }
     catch(Exception){
         ClassA.MyList.Add(stuff);
         return false;
     }
     return true;
}

正在编辑像这种不良做法的列表吗?或者可以吗?

编辑:当我的方法需要返回其他内容(bool,object,string等)时,我只是添加到列表中。

5 个答案:

答案 0 :(得分:2)

你通常不应该这样做。

您正在向您的班级客户端公开一个非常大的界面,这使您难以测试您的班级在所有情况下都能正常运行。如果有人在您不期待它时删除了值,会发生什么?或者,如果他们添加超出范围的值,该怎么办?您在List上调用方法时无法对其进行验证,因此您的类可能会在稍后的某个时间突然中断,因为可能很难找到错误数据的来源。

最好在您的班级上使用Add方法调用列表的Add,并将列表保密。然后,您可以控制客户端的操作,并且只显示他们需要使用的功能(以及您已经测试过的功能)。

答案 1 :(得分:2)

一般而言,班级应负责管理自己的内部状态。通过让这样的成员完全公开访问,你基本上是说A类放弃了该州的那部分责任。它无法对_myList包含的内容做出假设,因为任何人都可以随时更改它。

这是好还是不取决于你的意图,但它肯定与解耦和封装的想法背道而驰。同样,您是否想要解耦和封装取决于您。

更好的问题是确定A类和B类之间的哪种解耦对您的设计最有利,然后您就可以决定要公开哪个成员以及如何进行。

答案 2 :(得分:0)

这是一种非常常见的做法。不常见的是公开场合。将其设为私有,初始化A构造器上的列表,你就完全了。

public ObservableCollection<int> MyPublicList {get; private set;}

WPF充满了像这样的声明。

答案 3 :(得分:0)

一如既往,这取决于。如果要在类之外编辑列表(它是该类的接口的一部分)并且允许所有常规列表操作,则可以。如果只允许一部分操作,那么你不应该这样使用它 - 使用一个自定义列表(或列表中的包装器)来强制执行所有约束。例如,如果列表必须在类之外是只读的,那么您可以在类之外提供ReadOnlyCollection包装器。这一切都归结为强制数据完整性。

答案 4 :(得分:0)

这取决于您是否关心列表是否公开。露出&amp;访问公共的具体类型,您将公开实现细节并增加类与其使用者之间的耦合。您还限制ClassA强制执行数据一致性的机会,因为它的实现细节不再被正确封装。

有时,这是完全可以接受的,有时候,它不是。

我认为在对象模型愚蠢的情况下这是可以接受的。愚蠢,我的意思是它只包含数据。在将JSON / XML解析为对象时经常会发生这样的情况 - 事物的结构是为了镜像数据,而行为并不重要,因为它几乎没有。如果您只是在一个小代码库中进行攻击和/或变更的范围有限,或者涉及的行为非常少,那么它也更容易被接受。

但是,我通常会避免它。

首先,假设您添加到ClassA列表中的项目必须是素数。如果您编写AddItem()方法,则可以轻松强制执行此检查,但如果列表公开,则有效执行此操作会变得更加困难。

其次,假设您决定将列表更改为字典。您现在可能会破坏调用代码网站(ClassB,因为它们之前依赖于ClassA的实现细节。相反,如果您为AddItem()创建了名为RemoveItem()ClassA或类似的方法,则ClassB无关心内部实现是否为Set,Dictionary或List等,当改变时也不会破坏。

围绕'点缀事物'的指南(如blah.List[3].GetProduct(3).Reviews.First())有一个名称:The Law of Demeter

得墨忒耳法则的重点是:

  

基本概念是给定的对象应该假设为少   尽可能关于其他任何事物的结构或属性   (包括其子组件)。

您经常需要编写更多代码,但它会阻止更改。

相关问题