NameValueCollection에 키가 있는지 확인


141

키를 반복하지 않고 NameValueCollection에 키가 있는지 확인하는 빠르고 간단한 방법이 있습니까?

Dictionary.ContainsKey () 또는 이와 유사한 것을 찾고 있습니다.

물론 이것을 해결하는 방법에는 여러 가지가 있습니다. 누군가 내 뇌 가려움증을 긁을 수 있는지 궁금합니다.


당신 : 당신이 키를 기반으로 검색을 수행하려는 경우 BTW .... 사전을 사용할 수있는 이 클래스에 인덱서를 사용하지만이 자체를 반복 할 것 - 어떤 이득 때문에
카슨

답변:


181

에서 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)와.


38
이 속성은 다음과 같은 경우 null을 반환합니다. 1) 지정된 키를 찾을 수없는 경우; 2) 지정된 키가 발견되고 관련 키가 null 인 경우 이 속성은 두 경우를 구별하지 않습니다.
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

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의 인스턴스를 작성하는 클래스가 다른 클래스를 대신 사용하도록 전달되지는 않습니다.
lethek

12

예, 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))
{
   ...
}

1
O (n) 인 전체 컬렉션을 반복합니다. collection[key]내부적 Hashtable으로 O (1)를 사용 하는 동안
abatishchev

4
그러나 @abatishchev 그러나 collection[key]존재하지 않는 키와 해당 키에 대해 null 값이 저장되는 것을 구분하지 않습니다.
Rich O'Kelly

또한 리플렉션을 사용하여 더티 해킹을 수행하고 Hashtable의 개인 필드를 검색 할 수 있습니다.
abatishchev

나는 이것이 꽤 바보 같은 해결책이라고 생각합니다. 누군가가 NameValueCollection을 사용하는 경우 널 키와 같이 사전이 지원되지 않는 이유가 있습니다.
Chris Marisic

0

NameValueCollection에 지정된 키가 포함되어 있지 않으면 메서드를 반환하므로 메서드 Get를 사용하여 확인할 수 있습니다 .nullnull

MSDN을 참조하십시오 .


당신은 알 필요가 indexkey메소드를 호출 할 수 있습니다. 그렇지 않습니까?
abatishchev

0

컬렉션 크기가 작 으면 rich.okelly에서 제공하는 솔루션을 사용할 수 있습니다. 그러나 큰 모음은 사전의 생성이 키 모음을 검색하는 것보다 눈에 띄게 느려질 수 있음을 의미합니다.

또한 사용 시나리오에서 NameValueCollection이 수정 된 다른 시점에서 키를 검색하는 경우 매번 사전을 생성하는 것이 키 컬렉션을 검색하는 것보다 느릴 수 있습니다.


0

이것은 새로운 방법을 도입하지 않고도 해결책이 될 수 있습니다.

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

0

참조 소스에서 볼 수 있듯이 NameValueCollectionNameObjectCollectionBase 에서 상속 합니다.

따라서 기본 유형을 사용하고 리플렉션을 통해 개인 해시 테이블을 가져 와서 특정 키가 포함되어 있는지 확인하십시오.

모노에서도 작동하려면 해시 테이블의 이름이 모노인지 확인해야합니다. 여기서 볼 수있는 (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) {}이어야합니다. null인지 ""인지 확실하지 않지만 이것이 도움이됩니다.
CodeShouldBeEasy

올바른 구문은 메소드 호출 이 아닌 , Dictionary에서 MyNameValueCollection[Key]와 같이 데이터 구조 와 유사하다고 생각합니다 MyNameValueCollection(Key).
Blairg23

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

이것은 컬렉션에 키가 전혀 없는지 확인합니다. OP는 특정 키 의 존재를 요구했습니다 .
Bill Tür
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.