检查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
或""
但这应该有所帮助。