检查NameValueCollection中是否存在关键字

有没有一种快速简单的方法来检查一个键是否存在于一个NameValueCollection没有循环通过它?

寻找像Dictionary.ContainsKey()或类似的东西。

当然有很多方法可以解决这个问题。 只是想知道如果有人可以帮助我的头脑痒。

来自MSDN :

在下列情况下,此属性返回null:

1)如果指定的键没有find;

所以你可以只是:

NameValueCollection collection = ... string value = collection[key]; if (value == null) // key doesn't exist 

2)如果find指定的键并且其关联值为空。


collection[key]调用base.Get()然后base.FindEntry()内部使用Hashtable与性能O(1)。

使用这个方法:

 private static bool ContainsKey(NameValueCollection collection, string key) { if (collection.Get(key) == null) { return collection.AllKeys.Contains(key); } return true; } 

这是最有效的NameValueCollection ,并不取决于收集包含null值或不。

我不认为这些答案是正确的/最佳的。 NameValueCollection不仅不区分空值和缺失值,而且它的关键字也是不区分大小写的。 因此,我认为一个完整的解决scheme是:

 public static bool ContainsKey(this NameValueCollection @this, string key) { return @this.Get(key) != null // I'm using Keys instead of AllKeys because AllKeys, being a mutable array, // can get out-of-sync if mutated (it weirdly re-syncs when you modify the collection). // I'm also not 100% sure that OrdinalIgnoreCase is the right comparer to use here. // The MSDN docs only say that the "default" case-insensitive comparer is used // but it could be current culture or invariant culture || @this.Keys.Cast<string>().Contains(key, StringComparer.OrdinalIgnoreCase); } 

是的,您可以使用Linq来检查AllKeys属性:

 using System.Linq; ... collection.AllKeys.Contains(key); 

然而Dictionary<string, string[]>会更适合于这个目的,可能是通过扩展方法创build的:

 public static void Dictionary<string, string[]> ToDictionary(this NameValueCollection collection) { return collection.Cast<string>().ToDictionary(key => key, key => collection.GetValues(key)); } var dictionary = collection.ToDictionary(); if (dictionary.ContainsKey(key)) { ... } 

您可以使用Get方法并检查null因为如果NameValueCollection不包含指定的键,则该方法将返回null

请参阅MSDN 。

如果集合的大小很小,可以使用由rich.okelly提供的解决scheme。 然而,大量收集意味着字典的生成可能比仅仅search密钥集合慢得多。

另外,如果您的使用场景是在不同的时间点search键值,而NameValueCollection可能已被修改,则每次生成字典可能再次比search键集合要慢。

这也可以是一个解决scheme,而不必引入新的方法:

  item = collection["item"] != null ? collection["item"].ToString() : null; 

正如您在参考资源中看到的那样, NameValueCollectioninheritance自NameObjectCollectionBase 。

所以你采取基types,通过reflection得到私人散列表,并检查它是否包含一个特定的键。

为了使它在Mono中工作,你需要看看单声道的hashtable的名字是什么(m_ItemsContainer),如果初始的FieldInfo是null(mono-运行)。

喜欢这个

 public static class ParameterExtensions { private static System.Reflection.FieldInfo InitFieldInfo() { System.Type t = typeof(System.Collections.Specialized.NameObjectCollectionBase); System.Reflection.FieldInfo fi = t.GetField("_entriesTable", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); if(fi == null) // Mono fi = t.GetField("m_ItemsContainer", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); return fi; } private static System.Reflection.FieldInfo m_fi = InitFieldInfo(); public static bool Contains(this System.Collections.Specialized.NameValueCollection nvc, string key) { //System.Collections.Specialized.NameValueCollection nvc = new System.Collections.Specialized.NameValueCollection(); //nvc.Add("hello", "world"); //nvc.Add("test", "case"); // The Hashtable is case-INsensitive System.Collections.Hashtable ent = (System.Collections.Hashtable)m_fi.GetValue(nvc); return ent.ContainsKey(key); } } 

对于超纯粹的非reflection的.NET 2.0代码,您可以循环使用密钥,而不是使用散列表,但速度很慢。

 private static bool ContainsKey(System.Collections.Specialized.NameValueCollection nvc, string key) { foreach (string str in nvc.AllKeys) { if (System.StringComparer.InvariantCultureIgnoreCase.Equals(str, key)) return true; } return false; } 

在VB中是:

 if not MyNameValueCollection(Key) is Nothing then ....... end if 

在C#应该只是:

 if (MyNameValueCollection(Key) != null) { } 

不知道是否应该为null""但这应该有所帮助。