对于new()或Clear(),这就是问题所在

时间:2009-06-09 15:02:39

标签: .net

在我目前的工作场所,我遇到了很多类似于以下示例的代码:

private void GetWidgets(ref List<Widget> widgets){
  if(widgets == null){
    widgets = new List<Widget>();
  }
  else{
    widgets.Clear();
  }
  ... code to fill widget list
}    

public class Widgets{
  private List <Widget> widgets;
  ... other private members

  public Widgets(){    
    Clear();
  }

  public void Clear(){
    if(widgets == null){
      widgets = new List<Widget>();
    }
    else{
      widgets.Clear();
    }
    ... initialize other private members
  }
}    

我个人发现在这些示例中使用Clear方法会使代码变得更加丑陋和复杂。我不知道使用Clear方法而不是仅仅创建一个新List会有性能提升,但我更喜欢这样的代码:

private List<Widget> GetWidgets(){
  widgets = new List<Widget>();
  ... code to fill widget list;
  return widgets;
}

public class Widgets{
  private readonly List<Widgets> widgets = new List<Widget>();
  ... other private members

  public Widgets(){        
    ... initialize other private members
  }

  public Clear(){
    widgets.Clear();
  }
}
像这样的代码迫使你稍微改变你的开发模式,但我认为它使代码更具可读性并降低了复杂性。

除了这是一段匆忙编写的示例代码之外,我还大量使用具体类而不是接口等;你有什么看法?各自的优点和缺点是什么?

4 个答案:

答案 0 :(得分:12)

如果您有一个其他类可以访问的列表的共享引用,则Clear是一个更好的选项。在这种情况下,新建它将创建一个新的空列表,但是已创建对旧列表的引用的任何其他类仍将看到填充列表。

想象一下这种情况:

List<Widget> first;
myWidgets.GetWidgets(ref first);
List <Widget> second = first;
myWidgets.GetWidgets(ref second);

在上述情况下,如果使用Clear,则firstsecond将连接到同一列表。如果使用new,它们将连接到两个完全不同的列表。任何一种方法都会产生后果,而使用一种方法的决定取决于你想要实现的目标。

所以我想你问题的答案是:

    当你想确保每次调用new创建一个独立的,基本上不可变的列表时,
  • GetWidgets会更好。这在多线程应用程序中更好。如果将列表作为只读列表返回,您的服务会更好。
  • 当你想要表示一个列表时,
  • Clear会更好,并且引用它的所有类都会看到对该列表的更改。如果您进行多线程处理,则会产生许多争用问题。

答案 1 :(得分:1)

如果有对此列表的引用需要这种类型的代码,那么我认为需要重新设计一些东西。尝试无副作用的函数,这不是因为它既是构造对象又是操纵状态,这可能会在其他地方产生影响。

答案 2 :(得分:0)

就个人而言,我喜欢

public class Widgets {
  private readonly List <Widget> widgets = new List<Widget>();
  ... 
  public void Clear() {
      widgets.Clear();
    ...
  }
}

列表仅在一个地方和一个地方创建; Clear()是明确的,直截了当的,简单的,无条件的。代码更少,复杂性更低。

我在这里使用readonly提醒我 - 强行,当我写错了代码 - 我已经完成了创建列表,重新创建它是错误的。

使用正确的C#语法更新,感谢Joel Mueller的有用评论。

答案 3 :(得分:0)

还要考虑垃圾收集 - 如果你经常使用new(),那么会在堆上创建大量必须进行垃圾收集的对象,但Clear()不会创建任何新堆对象(虽然这只是一个问题,如果你这样做了数千次)