web-dev-qa-db-ja.com

NameValueCollectionにキーが存在するかどうかを確認します

キーをループせずにNameValueCollectionに存在するかどうかをすばやく簡単に確認する方法はありますか?

Dictionary.ContainsKey()などのようなものを探しています。

もちろん、これを解決する方法はたくさんあります。誰かが私のかゆみを掻くのを助けることができるかどうか疑問に思っています。

131
Muhammad Yussuf

MSDN から:

このプロパティは、次の場合にnullを返します。

1)指定されたキーが見つからない場合。

したがって、次のことができます。

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

2)指定されたキーが見つかり、関連する値がヌルの場合。

collection[key]base.Get()を呼び出し、次にbase.FindEntry()が内部的にHashtableを使用して、パフォーマンスO(1)で呼び出します。

163
abatishchev

この方法を使用します。

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

    return true;
}

これはNameValueCollectionに最も効率的で、コレクションにnull値が含まれているかどうかに依存しません。

48

私はこれらの答えがまったく正しい/最適だとは思わない。 NameValueCollectionは、null値と欠損値を区別しないだけでなく、キーに関しても大文字と小文字を区別しません。したがって、完全なソリューションは次のようになると思います。

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

はい、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))
{
   ...
}
12
Rich O'Kelly

私は小さな要素のコレクションで働いていたときに、このコレクションを使用しています。

要素が多い場合、「辞書」を使用する必要があると思います。私のコード:

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

またはこれを使用することもできます:

 string prodId = _cfg.ProdIdes[key] !=null ? "found" : "not found";
0
Roberto Gata

コレクションのサイズが小さい場合、rich.okellyが提供するソリューションを使用できます。ただし、コレクションが大きいということは、キーコレクションを検索するよりも辞書の生成が著しく遅くなる可能性があることを意味します。

また、使用シナリオが異なる時点でキーを検索している場合、NameValueCollectionが変更されている可能性があり、そのたびに辞書を生成することは、単にキーコレクションを検索するよりも遅くなる可能性があります。

0
Jaguar

これは、新しいメソッドを導入する必要のないソリューションでもあります。

    item = collection["item"] != null ? collection["item"].ToString() : null;
0
codys-hole

参照ソースでわかるように、- NameValueCollectionNameObjectCollectionBase を継承しています。

したがって、ベースタイプを取得し、リフレクションを介してプライベートハッシュテーブルを取得し、特定のキーが含まれているかどうかを確認します。

Monoでも同様に機能するには、hashtableの名前がmonoであるかどうかを確認する必要があります。これは here (m_ItemsContainer)であり、初期FieldInfoはnull(モノランタイム)です。

このような

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;
}
0
Stefan Steiger

NameValueCollectionに指定されたキーが含まれていない場合、メソッドはGetを返すため、nullメソッドを使用してnullを確認できます。

MSDN を参照してください。

0
Codrin Eugeniu
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;
        }
0
userSteve

VBでは次のとおりです。

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

C#では次のようにします。

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

nullまたは""のどちらであるかはわかりませんが、これで解決するはずです。

0