.NET中是否有任何阻止空条目的集合?

我专门考虑一个符合一套合同的集合,但我认为这个问题适用于任何类型。 .NET框架中是否存在阻止空条目的集合? 我想要的具体行为是这样的:

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

这不是内置HashSet 。 是否存在任何具有此(或类似)行为的集合,或者我最好自己滚动? 如果是后者,最好的方法是什么? 我应该直接从HashSetinheritance还是只包装它?

编辑:要清楚,这只是空闲的想知道。 主要是因为我想不出有任何理由我想让null进入一组对象。 我对此没有任何特别需要。

除了这个单一行为之外,没有像HashSet那样的内置类。

如果你需要这个,我建议你自己动手。 但是,我不建议HashSet 。 没有一种方法(比如Add ,你明确想要改变)是虚拟的,因为它并没有真正考虑到子类化。 这将导致奇怪的使用行为,因为您将隐藏inheritance的方法。

只需封装一个HashSet ,然后公开您需要的成员。 您必须添加的唯一真正的“代码”是对Add方法的单个空检查 – 否则,只需将所有方法传递给封装的实例。

如果您希望这是一个generics类,则需要添加一个额外的约束才能使用类,因为您希望进行空检查:

 public class ValueSet : ICollection, IEnumerable, ICollection where T : class { private HashSet hashSet = new HashSet(); // ... Implement all members as needed... 

怎么样为HashSet编写扩展方法。 这可能是最简单的事情。

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

然后你可以这样做:

 HashSet test = new HashSet(); test.AddNonNull(null); //Will return false; 

当你用generics标记这个问题时,我想你正在寻找一个通用的集合。 .NET框架中不存在这样的集合,因为值类型不能null ,所以我猜你应该通过在它接受的generics类型上添加约束限制来自行编译。

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

我很可能从System.Collections.ObjectModel.Collection类开始,用于滚动自己的类。

System.Collections.Generics.Dictionary不允许为TKey添加null (抛出exception)。 如果你打算以这种方式使用它,你必须忽略你的场景中的TValue ,并且function类似于Hashset ,当然除了花哨的设置操作。

肯定有点笨拙,但在此之前,对于你来说,这可能是一个可靠的解决方法,然后才能想出你自己喜欢的collections类型。

即使您设法阻止添加空条目,您也无法阻止在集合中使用HAVING空条目 – 至少不能通过您的Set类。

取任何Set ,其中T是可空类型。 添加一些非空条目后,您可以将其中任何一个条目设置为null。 由于该命令与Set类无关,因此Set类无法检测也无法阻止它。

两种选择:

编辑:对不起我错过了他需要一套而不是一个集合。 至少我列出的首选项目仍然有效。 🙂

首选:

在将项添加到集合的方法中,如果使用无效值调用它们,则抛出ArgumentNullException

不是首选:

派生自Collection并覆盖InsertItemSetItem ,如果值为null,则抛出ArgumentNullException

在任何情况下,您都可以使用.NET 4.0中的代码约定来防止将null值添加到集合中。 这样,您还将获得编译时检查代码是否正确(使用Code Contracts提供的静态分析):

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

}

ContractInvariantMethod标记的方法指定应始终保持的条件(列表中没有null元素)。 我相信静态分析不能解释这个(因为ForAll ),但我可能错了。 但是,它当然可以检查您是否使用正确(非null)参数调用Add方法。

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

 public void MyMethod(HashSet 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(); } } 

你将不得不自己动手。 如果你想让Add返回一个bool(无论该项是非null,因此是添加还是相反),你必须从头开始。 我可能会建议inheritanceList并抛出ArgumentNullExceptions。 我的意思是如果你真的不想要添加空值,exception可能是最好的方式,肯定会更容易。