检查 NameValueCollection 中是否存在密钥

有没有一种快速而简单的方法来检查 NameValueCollection 中是否存在密钥,而不需要循环访问它?

查找类似 Dictionary. ContainsKey ()或类似的内容。

当然有很多方法可以解决这个问题。只是想知道是否有人可以帮我挠挠头痒。

119168 次浏览

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

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

然而,Dictionary<string, string[]>更适合这一目的,或许可以通过扩展方法创建:

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

来自 MSDN:

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

1)如未能找到指定的密码匙;

所以你可以:

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

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

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

此方法处理键位于集合内且其关联值为空时的情况。

private static bool ContainsKey(this NameValueCollection collection, string key) =>
collection.Get(key) is not null || collection.AllKeys.Contains(key);

从 C # 9开始,您可以使用 is not null,否则使用 != null

如果集合的大小很小,那么可以使用 rich.okelly 提供的解决方案。但是,大型集合意味着字典的生成可能明显慢于仅搜索键集合。

此外,如果您的使用场景在不同的时间点(NameValueCollection 可能已经被修改)搜索键,那么每次生成字典可能会比仅仅搜索键集合要慢。

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

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);
}

这也可能是一种解决办法,而不必采用新的方法:

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

正如您在参考资料中看到的,NameValueCollection继承自 NameObjectCollectionBase

因此,使用基类型,通过反射获取私有散列表,并检查它是否包含特定的键。

为了让它也能在 Mono 中工作,您需要查看 Mono 中散列表的名称,这是您可以看到的 给你(m _ ItemsContainer) ,如果初始 FieldInfo 为 null (Mono-running) ,则获取 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);
}
}

用于超纯非反射式。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"",但这应该有帮助。

NameValueCollection n = Request.QueryString;


if (n.HasKeys())
{
//something
}

返回值 类型: System. Boolean 如果 NameValueCollection 包含不为空的键,则为 true; 否则为 false。 < a href = “ https://msdn.microsoft.com/en-us/library/system.Collections.specalized.NameValueCollection.haskeys (v = vs. 110) .aspx”rel = “ nofollow noReferrer”> LINK

当我在处理小元素集合时,我正在使用这个集合。

在元素很多的地方,我认为需要使用“字典”。 我的代码:

NameValueCollection ProdIdes;
string prodId = _cfg.ProdIdes[key];
if (string.IsNullOrEmpty(prodId))
{
......
}

或者可以这样使用:

 string prodId = _cfg.ProdIdes[key] !=null ? "found" : "not found";
queryItems.AllKeys.Contains(key)

注意键可能不是唯一的,比较通常是区分大小写的。如果你只想得到第一个匹配键的值,而不想考虑大小写,那么使用以下方法:

        public string GetQueryValue(string queryKey)
{
foreach (string key in QueryItems)
{
if(queryKey.Equals(key, StringComparison.OrdinalIgnoreCase))
return QueryItems.GetValues(key).First(); // There might be multiple keys of the same name, but just return the first match
}
return null;
}