代码之家  ›  专栏  ›  技术社区  ›  Sean Devlin

.NET中是否有防止空项的集合?

  •  14
  • Sean Devlin  · 技术社区  · 15 年前

    我特别考虑一个集合,它满足集合的契约,但我认为这个问题可以应用于任何类型。.NET framework中是否有防止空项的集合?我想要的具体行为是:

    var set = new HashSet<object>();
    bool added = set.Add(null);
    Console.WriteLine(added); // prints "False"
    

    HashSet<T> . 是否有任何收藏具有这种(或类似)行为,或者我最好还是自己制作?如果是后者,最好的方法是什么?我应该直接继承他的遗产吗 还是把它包起来?

    编辑:澄清一下,这只是一个空想。主要是因为我想不出任何理由 希望 容许 null 变成一组对象。我没有什么特别的需要。

    10 回复  |  直到 15 年前
        1
  •  13
  •   Sam Harwell    15 年前

    没有像这样的内置类 HashSet<T> 除了这个单一的行为。

    如果你需要这个,我建议你自己滚。我不建议子类化 HashSet<T> 然而。没有一种方法(如 Add ,您明确希望更改)是虚拟的,因为它在设计时并没有真正考虑子类化。这将导致奇怪的使用行为,因为您将隐藏继承的方法。

    HashSet<T> ,并公开所需的成员。您需要添加的唯一真正的“代码”是add方法上的一个null检查——否则,只需将所有方法传递给封装的实例。

    public class ValueSet<T> : ICollection<T>, IEnumerable<T>, ICollection
        where T : class
    {
         private HashSet<T> hashSet = new HashSet<T>();
         // ... Implement all members as needed...
    
        2
  •  7
  •   Sam Harwell    15 年前

    为HashSet编写一个扩展方法怎么样。这可能是最容易做到的事情。

    public static class HashSetExtensions
    {
        public static bool AddNonNull<T>(this HashSet<T> set, T item)
            where T : class
        {
            if (item == null)
                return false;
    
            return set.Add(item);
        }
    }
    

    HashSet<object> test = new HashSet<object>();
    test.AddNonNull(null); //Will return false;
    
        3
  •  3
  •   Darin Dimitrov    15 年前

    当你在这个问题上加上 generics 我想你是在找一个普通的收藏品。这种集合在.NET framework中不存在,只是因为值类型不同 null ,所以我想您应该通过在它接受的泛型类型上添加一个约束来实现。

        4
  •  2
  •   herzmeister    15 年前

    System.Collections.Generics.Dictionary<TKey, TValue> null 对于 TKey (抛出异常)。你必须忽略 TValue Hashset<T> ,当然,除了花哨的集合操作。

    当然有点笨拙,但在你能想出自己喜欢的收藏类型之前,这可能是一个可靠的解决办法。

        5
  •  1
  •   Mitchel Sellers    15 年前

    我不知道有任何.NET集合会这样做,因为根据传递的类型,null实际上是一个有效的条目,因此,添加是成功的。

    我最有可能从System.Collections.ObjectModel.Collection类开始,以实现您自己的滚动。

        6
  •  1
  •   Kjara    8 年前

    即使您设法阻止添加空条目,您也无法阻止集合中存在空条目-至少不能通过 Set

    随便吃 Set<T> T 是可为空的类型。在添加了一些非null条目之后,可以获取其中任何一个条目并将其设置为null。因为那个命令和 设置 类,则无法检测到它,也无法阻止它 设置 班级。

        7
  •  0
  •   Sam Harwell    15 年前

    两种选择:

    编辑:

    首选:

    ArgumentNullException 如果使用无效值调用它们。

    非首选:

    Collection<T> InsertItem SetItem 如果该值为空。

        8
  •  0
  •   Tomas Petricek    15 年前

    在任何情况下,都可以使用.NET4.0中的代码契约来防止 null

    public class MyClass {
      private List<Something> nonNullList;
    
      [ContractInvariantMethod]
      void NonNullEntries() {
        Contract.Invariant(Contract.ForAll(nonNullList, el => el != null));
      }
    
      public void Add(Something el) {
        Contract.Requires(el != null);
      }
    

    }

    ContractInvariantMethod 指定应始终保持的条件(没有 无效的 ForAll ),但我可能错了。不过,它当然可以检查你是否在打电话 Add

        9
  •  0
  •   tomosius    8 年前

    正如其他人所回答的,没有一个Set类不允许空值。话虽如此,我将分享我在一些情况下使用的一个简单解决方案。在我的例子中,我正在设计接受HashSet参数的方法,因为我需要确保获得唯一的对象。我不希望集合中可能存在null,也不希望每次枚举项并对其执行操作时都检查null。我的解决方案是简单地调用remove null,以防出现null。

    public void MyMethod(HashSet<SomeType> set)
    {
        // remove null item in case it's there
        set.Remove(null);
    
        foreach (var item in set)
        {
            // safe to assume item is not null
            item.DoSomething();
        }
    }
    
        10
  •  -1
  •   hackerhasid    15 年前

    你得自己滚。如果您希望Add返回bool(无论该项是否为非null并因此添加或反向添加),那么您必须从头开始。我可能建议从列表继承并抛出异常。我的意思是,如果您真的不想添加null,那么异常可能是最好的方法,而且肯定会更容易。