159

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

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

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

4

12 回答 12

204

来自MSDN

此属性在以下情况下返回 null:

1)如果没有找到指定的key;

所以你可以:

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

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

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

于 2012-03-26T08:23:12.030 回答
61

此方法处理 key 在集合中并且其关联值为 null 的情况。

private static bool ContainsKey(this NameValueCollection collection, string key) =>
    collection.Get(key) != null || collection.AllKeys.Contains(key);
于 2012-03-26T08:48:56.080 回答
17

我认为这些答案中的任何一个都不是非常正确/最佳的。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);
}
于 2014-01-25T17:08:56.067 回答
16

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

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

然而 aDictionary<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))
{
   ...
}
于 2012-03-26T08:21:21.580 回答
1
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;
        }
于 2018-08-02T14:57:55.983 回答
0

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

请参阅MSDN

于 2012-03-26T08:22:34.480 回答
0

如果集合大小很小,您可以使用rich.okelly 提供的解决方案。但是,大型集合意味着字典的生成可能比仅搜索键集合要慢得多。

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

于 2012-03-26T08:57:10.703 回答
0

这也可以是一个无需引入新方法的解决方案:

    item = collection["item"] != null ? collection["item"].ToString() : null;
于 2015-06-11T08:37:49.423 回答
0

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

因此,您采用基本类型,通过反射获取私有哈希表,并检查它是否包含特定密钥。

为了让它也能在 Mono 中工作,您需要查看单声道中哈希表的名称是什么,您可以在此处看到(m_ItemsContainer),如果初始 FieldInfo 为空 (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;
}
于 2015-09-17T11:37:50.437 回答
0

在VB中是:

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

在 C# 中应该只是:

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

不确定是否应该这样做null,或者""但这应该有所帮助。

于 2015-10-26T13:32:17.947 回答
0

当我在小元素集合中工作时,我正在使用这个集合。

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

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

或者可以使用这个:

 string prodId = _cfg.ProdIdes[key] !=null ? "found" : "not found";
于 2018-01-23T15:14:43.567 回答
-1
NameValueCollection n = Request.QueryString;

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

返回值 类型:System.Boolean 如果 NameValueCollection 包含不为空的键,则为真;否则为假。关联

于 2017-12-07T10:11:08.593 回答