.NET中是否有任何阻止空条目的集合?
我专门考虑一个符合一套合同的集合,但我认为这个问题适用于任何类型。 .NET框架中是否存在阻止空条目的集合? 我想要的具体行为是这样的:
var set = new HashSet(); bool added = set.Add(null); Console.WriteLine(added); // prints "False"
这不是内置HashSet
。 是否存在任何具有此(或类似)行为的集合,或者我最好自己滚动? 如果是后者,最好的方法是什么? 我应该直接从HashSet
inheritance还是只包装它?
编辑:要清楚,这只是空闲的想知道。 主要是因为我想不出有任何理由我想让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
当你用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
并覆盖InsertItem
和SetItem
,如果值为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可能是最好的方式,肯定会更容易。