代码之家  ›  专栏  ›  技术社区  ›  John Kraft

对于new()或clear(),这是一个问题

  •  2
  • John Kraft  · 技术社区  · 16 年前

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

    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方法是否比简单地创建一个新列表有性能提高,但是我更喜欢这样的代码:

    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 回复  |  直到 16 年前
        1
  •  12
  •   Michael Meadows    16 年前

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

    想象一下这个场景:

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

    在上述情况下,如果 Clear 被雇用, first second 将连接到同一列表。如果 new 如果被雇佣,他们将被连接到两个完全不同的列表。任何一种方法都会有后果,使用一种方法而不是另一种方法的决定将取决于您试图实现的目标。

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

    • 新的 当你想确保每次呼叫 GetWidgets 创建一个独立的、本质上不可变的列表。这在多线程应用程序中更好。如果将列表作为只读列表返回,则会得到更好的服务。
    • 清除 如果希望表示一个列表,并且引用该列表的所有类都可以看到对该列表所做的更改,则更好。如果您是多线程的,这会产生许多争用问题。
        2
  •  1
  •   JC.    16 年前

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

        3
  •  0
  •   Carl Manaster    16 年前

    我个人喜欢

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

    列表只在一个地方和一个地方创建;clear()是明确的、直接的、简单的和无条件的。更少的代码,更少的复杂性。

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

    更新的 由于Joel Mueller的有益评论,使用正确的C语法。

        4
  •  0
  •   thecoop    16 年前

    还需要考虑垃圾收集-如果您经常使用new(),那么这将在堆上创建许多必须进行垃圾收集的对象,但clear()不会创建任何新的堆对象(尽管这只是一个问题,如果您这样做了数千次)