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


141

ループすることなくキーがNameValueCollectionに存在するかどうかを確認する迅速で簡単な方法はありますか?

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

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


あなたは:ちょうどあなたがキーに基づいて検索を行いたい場合はところで....辞書を使うことができ、このクラスにインデクサを使用するが、これは自分自身をループ行います-ノーゲインそう
カルステン

回答:


181

MSDNから:

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

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

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

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

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

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


37
このプロパティは、次の場合にnullを返します。1)指定されたキーが見つからない場合。2)指定されたキーが見つかり、それに関連する値がnullの場合。このプロパティは、2つのケースを区別しません。
Steve

1
@Andreasだから、nullの代わりに空の文字列を保存する方がよい
abatishchev

@Steve OPは、このような衝突については何も述べていません。
abatishchev

13
正しい@abatishchevですが、OPは「キーが存在するかどうかを確認する」と言っています。キーが存在しないためnullを取得することは正しくありません。最後には妥協なしには答えはありません(ループなし、空の文字列を使用)
Steve

@abatishchevは「0等しい」と言っているようなものですnull... sry
Andreas Niedermair

54

この方法を使用します。

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

    return true;
}

これは、NameValueCollectionコレクションにnull値が含まれているかどうかに関係なく、最も効率的です。


5
using System.Linq;このソリューションを使用するときは、覚えておいてください。
jhauberg 2012

14

これらの答えはどれもまったく正しくない/最適ではないと思います。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);
}

私はこのソリューションが好きです。NameValueCollectionBaseソースを見ると、デフォルトでInvariantCultureIgnoreCaseを使用していますが、これは、NameValueCollectionのインスタンスを作成するクラスが代わりに使用するために別のものが渡されないという意味ではありません。
レセック

12

はい、Linqを使用してAllKeysプロパティを確認できます。

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

ただし、a 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))
{
   ...
}

1
これは、O(n)であるコレクション全体をループします。一方、collection[key]内部的に使用するHashtableO(1)である
abatishchev

4
@abatishchevただしcollection[key]、実際には、存在しないキーとそのキーに対して格納されているnull値は区別されません。
リッチ・オケリー

また、リフレクションを使用してダーティーハックを実行し、Hashtableのプライベートフィールドを取得できます。
abatishchev 2012年

これはかなりばかげた解決策だと思います。誰かがNameValueCollectionを使用している場合、nullキーを持つなど、辞書がサポートされていない可能性があります。
Chris Marisic 2014

0

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

MSDNを参照してください。


メソッドを呼び出すにindexは、を知っている必要がありkeyます。ね?
abatishchev

0

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

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


0

これは、新しい方法を導入する必要のない解決策になる可能性もあります。

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

0

あなたは参考情報源に見ることができるように、NameValueCollectionのは、から継承NameObjectCollectionBase

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

Monoでも機能するためには、ハッシュテーブルの名前がMonoで何であるかを確認する必要があります。これは、ここで確認できます。(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);
    }
}

超純粋な非反射.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

VBの場合:

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

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

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

それがあるべきかどうかわからないnull""が、これは役立つはずです。


VBで申し訳ありません。C#はif(MyNameValueCollection(Key)!= null){}である必要があります。
CodeShouldBeEasy 2015年

正しい構文は、メソッドの呼び出しを期待するではなくDictionary、のようなデータ構造に似ていると思います。MyNameValueCollection[Key]MyNameValueCollection(Key)
Blairg23 2016年

0

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

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

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

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

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

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

-1
NameValueCollection n = Request.QueryString;

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

戻り値の型:System.Boolean NameValueCollectionにnull以外のキーが含まれている場合はtrue。それ以外の場合はfalse。リンク


2
これは質問に答えるかもしれませんが、特にこれが他の多くの答えの良い代替になる可能性がある方法を説明するために、いくつかの説明はしばしば高く評価されます。
Pac0 2017

これは、コレクションにキーが含まれているかどうかを確認するだけです。OPは、特定のキーの存在を要求しました。
BillTürDec
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.