키가 없으면 C # Dictionary <int, int> 조회는 어떻게 되나요?


121

null 검사를 시도했지만 컴파일러는이 조건이 발생하지 않을 것이라고 경고합니다. 무엇을 찾아야합니까?

답변:


196

가있는 경우 값을 얻으려면 다음을 사용하십시오 Dictionary<TKey, TValue>.TryGetValue.

int value;
if (dictionary.TryGetValue(key, out value))
{
    // Key was in dictionary; "value" contains corresponding value
} 
else 
{
    // Key wasn't in dictionary; "value" is now 0
}

(사용 ContainsKey하고 인덱서를 사용하면 키가 두 번 표시되며 이는 매우 무의미합니다.)

참조 유형 사용 하는 경우에도 null 검사는 작동하지 않습니다 Dictionary<,>. null을 반환하는 대신 누락 된 키를 요청하면에 대한 인덱서 에서 예외가 발생합니다. (이 사이에 큰 차이가 Dictionary<,>Hashtable.)


@JonSkeet TryGetValue도 이중 조회를 수행하지 않습니까 ( 이 질문 본문에 명시된대로 )?
nawfal

5
@nawfal : 그 질문에 전혀 언급이 없다는 표시가 없습니다. 그것은 ContainsKey가치를 추출해야하기 때문에 그것이 사실 인 것보다 더 많은 일을하고 있다고 말한다 . 그래도 두 번 조회하지 않습니다.
Jon Skeet

순진하게도 null을 예상했지만 Dictionary <TKey, enum>의 경우 열거 형에서 "0"에 해당하는 값을 반환합니다.
Jess

23

사전에 KeyNotFound키가 포함되어 있지 않은 경우 사전에서 예외 가 발생합니다.

제안 된대로 ContainsKey적절한 예방 조치입니다. TryGetValue효과적입니다.

이를 통해 사전은 null 값을보다 효과적으로 저장할 수 있습니다. 이런 식으로 작동하지 않으면 [] 연산자의 null 결과를 확인하면 null 값 또는 좋지 않은 입력 키가 없음을 나타냅니다.


추가 정보는 MSDN에서 찾을 수 있습니다. msdn.microsoft.com/en-gb/library/9tee9ht2.aspx
cyberzed

10

새 값을 추가하기 전에 확인하는 경우 다음 ContainsKey방법을 사용하십시오 .

if (!openWith.ContainsKey("ht"))
{
    openWith.Add("ht", "hypertrm.exe");
}

값이 있는지 확인하는 경우 TryGetValueJon Skeet의 답변에 설명 된 방법을 사용하십시오 .


8
TryGet이 더 좋습니다
Ruben Bartelink

2
포함 후 즉시 가져 오면 해시 테이블을 통해 키 조회를 두 번 해결합니다. Wintellect PowerCollections에는 또한 GetValueElseAdd값 (또는 a Func<TValue>)을 제공하여 삽입물에 해상도가없는 경우 추가하려는 경우에도 저장하는 메서드가 있습니다 . 추가 경로가 덜 자주 있기 때문에 내가 었소는 .NET libs와에 그것을 만든 이유를 추측하는 것은 당신은 캐시 stylee]에서를 사용하는 경우
루벤 Bartelink

@rub : 코드의 목적에 따라 다릅니다. 값을 사용하고 싶다면 TryGetValue더 좋을 것이라는 데 동의 하지만 중복 추가를 피하기 위해 사전에 키가 포함되어 있는지 확인하려면 ContainsKey(더 좋지 않다면) 그대로 라고 말할 것 입니다.
Fredrik Mörk

@Fredrik는 다음과 같은 경우 에만 봉쇄 확인을하고 싶은, 다음 네, 그것의 가치는 ContainsKey를 사용하여. 이 답변의 샘플 코드에서는 그렇지 않습니다.
Jon Skeet

@Jon : 사실, 실제로 추가 된 가치가 추가 된 직후에 가져 왔다는 사실을 놓쳤습니다.
Fredrik Mörk

3

값을 꺼내기 전에 Dictionary.ContainsKey (int key)를 확인해야합니다.

Dictionary<int, int> myDictionary = new Dictionary<int, int>();
myDictionary.Add(2,4);
myDictionary.Add(3,5);

int keyToFind = 7;
if(myDictionary.ContainsKey(keyToFind))
{
    myValueLookup = myDictionay[keyToFind];
    // do work...
}
else
{
    // the key doesn't exist.
}

2
조회를 두 번 수행하는 이유는 무엇입니까?
Jon Skeet

2
@mookid : 제 생각에는 아닙니다. 아이디어는 열쇠를 찾아보고 발견되면 하나의 조치를 취하고 그렇지 않으면 다른 조치를 취하는 것입니다.
Jon Skeet

3
@Jon-솔직히? 에 대해 몰랐기 때문 TryGetValue입니다. 고맙게도 지금하고 있으므로 나중에 알게 될 것입니다. 'cos 토론은 가치가 있지만이 답변은 그대로 두겠습니다.
ZombieSheep

@Jon Skeet-내가 여기있는 이유입니다. :)
ZombieSheep

@JonSkeet C # 7 이전 TryGetValue에는 람다 식에서 사용할 수 없었기 때문 입니다. 그래도 C #에 대한 새로운 확장 catchnull병합 연산자 와 유사한 연산자 라고 생각합니다 .
NetMage

1

도우미 클래스가 편리합니다.

public static class DictionaryHelper
{
    public static TVal Get<TKey, TVal>(this Dictionary<TKey, TVal> dictionary, TKey key, TVal defaultVal = default(TVal))
    {
        TVal val;
        if( dictionary.TryGetValue(key, out val) )
        {
            return val;
        }
        return defaultVal;
    }
}

왜 이것이 표준 라이브러리에 추가되지 않는지 궁금합니다. 해시 맵을 사용하는 거의 모든 언어는 항목이없는 경우 null을 반환하고 이상한 예외는 아닙니다. 사전에없는 항목은 예외적 인 동작이 아닙니다.
Adam Hess 19 년

@AdamHess - 당신은 C #에서의 Hashtable ()를 가지고 이유 ... 불행하게도, 당신의 키는 :( ...이 박스 얻을
veljkoz

0

ContainsKey 는 당신이 찾고있는 것입니다.


0

아마도 다음을 사용해야합니다.

if(myDictionary.ContainsKey(someInt))
{
  // do something
}

null을 확인할 수없는 이유는 여기서 키가 값 유형이기 때문입니다.


1
null을 확인하면 원하는 효과를 얻지 못하므로 값 유형은 다소 관련이 없습니다.
Jon Skeet

@Johannes, Jon의 솔루션은 물론 훨씬 더 좋지만 질문자는 키가 있는지 확인했으며 Dictionary <int, int>이므로 키도 여기에서 값 유형입니다.
Razzie

0
int result= YourDictionaryName.TryGetValue(key, out int value) ? YourDictionaryName[key] : 0;

키가 사전에 있으면 키 값을 반환하고 그렇지 않으면 0을 반환합니다.

희망,이 코드가 도움이됩니다.


1
키가있는 경우이 코드는 두 번 조회됩니다. TryGetValue충분히 사용하는 것입니다 value대신result
마티유 VIALES는

0

이 특정 사전을 캡슐화하는 옵션을 고려하고 해당 키의 값을 반환하는 메서드를 제공합니다.

public static class NumbersAdapter
{
    private static readonly Dictionary<string, string> Mapping = new Dictionary<string, string>
    {
        ["1"] = "One",
        ["2"] = "Two",
        ["3"] = "Three"
    };

    public static string GetValue(string key)
    {
        return Mapping.ContainsKey(key) ? Mapping[key] : key;
    }
}

그런 다음이 사전의 동작을 관리 할 수 ​​있습니다.

예 : 사전에 키가 없으면 매개 변수로 전달한 키를 반환합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.