[c#] 사전에 추가하는 다양한 방법

Dictionary.add(key, value)과 의 차이점은 무엇입니까 Dictionary[key] = value?

ArgumentException중복 키를 삽입 할 때 마지막 버전이 던지지 않는다는 것을 알았는데 첫 번째 버전을 선호하는 이유가 있습니까?

편집 : 누구든지 이것에 대한 정보의 권위있는 출처를 가지고 있습니까? 나는 MSDN을 시도했지만 항상 야생 거위 추적입니다 🙁



답변

성능은 거의 100 % 동일합니다. Reflector.net에서 클래스를 열어 확인할 수 있습니다.

This 인덱서입니다.

public TValue this[TKey key]
{
    get
    {
        int index = this.FindEntry(key);
        if (index >= 0)
        {
            return this.entries[index].value;
        }
        ThrowHelper.ThrowKeyNotFoundException();
        return default(TValue);
    }
    set
    {
        this.Insert(key, value, false);
    }
}

그리고 이것은 Add 메서드입니다.

public void Add(TKey key, TValue value)
{
    this.Insert(key, value, true);
}

다소 길기 때문에 전체 Insert 메서드를 게시하지는 않지만 메서드 선언은 다음과 같습니다.

private void Insert(TKey key, TValue value, bool add)

함수에서 더 아래로 내려 가면 다음과 같은 일이 발생합니다.

if ((this.entries[i].hashCode == num) && this.comparer.Equals(this.entries[i].key, key))
{
    if (add)
    {
        ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
    }

키가 이미 존재하는지 확인하고 존재하고 매개 변수 add가 true이면 예외를 발생시킵니다.

따라서 모든 목적과 의도에 대해 성능은 동일합니다.

다른 몇 가지 언급과 마찬가지로 동일한 키를 두 번 추가하려는 시도에 대해 확인이 필요한지 여부에 관한 것입니다.

긴 게시물에 대해 죄송합니다. 괜찮기를 바랍니다.


답변

첫 번째 버전은 새 KeyValuePair를 사전에 추가하여 키가 이미 사전에 있으면 던집니다. 두 번째는 인덱서를 사용하여 키가없는 경우 새 쌍을 추가하지만 사전에 이미있는 경우 키 값을 덮어 씁니다.

IDictionary<string, string> strings = new Dictionary<string, string>();

strings["foo"] = "bar";          //strings["foo"] == "bar"
strings["foo"] = string.Empty;   //strings["foo"] == string.empty
strings.Add("foo", "bar");       //throws     


답변

Dictionary.Add(key, value)Dictionary[key] = value다른 목적을 가지고 :

  • Add메서드를 사용하여 새 키 / 값 쌍 을 추가 하면 기존 키가 대체되지 않습니다 ( ArgumentException가 발생 함).
  • 키가 사전에 이미 있는지 여부를 신경 쓰지 않는 경우 인덱서를 사용합니다. 즉, 키가 사전에 없으면 키 / 값 쌍을 추가하고 키가 이미 있으면 지정된 키의 값을 바꿉니다. 사전에.

답변

먼저 질문에 답하려면 사전의 목적과 기본 기술을 살펴 봐야합니다.

DictionaryKeyValuePair<Tkey, Tvalue>각 값이 고유 키로 표시되는 목록입니다 . 좋아하는 음식 목록이 있다고 가정 해 보겠습니다. 각 값 (음식 이름)은 고유 한 키 (위치 =이 음식을 얼마나 좋아하는지)로 표시됩니다.

예제 코드 :

Dictionary<int, string> myDietFavorites = new Dictionary<int, string>()
{
    { 1, "Burger"},
    { 2, "Fries"},
    { 3, "Donuts"}
};

건강을 유지하고 마음이 바뀌었고 좋아하는 “버거”를 샐러드로 바꾸고 싶다고 가정 해 보겠습니다. 목록은 여전히 ​​즐겨 찾기 목록이며 목록의 특성은 변경되지 않습니다. 당신이 가장 좋아하는 것은 목록에서 1 위를 유지하고 그 가치 만이 변할 것입니다. 이것은 당신이 이것을 부를 때입니다 :

/*your key stays 1, you only replace the value assigned to this key
  you alter existing record in your dictionary*/
myDietFavorites[1] = "Salad";

하지만 당신이 프로그래머라는 사실을 잊지 마세요. 이제부터 당신의 문장은; 이모티콘은 컴파일 오류가 발생하고 모든 즐겨 찾기 목록이 0 인덱스 기반이기 때문에 사용을 거부합니다.

식단도 바뀌 었습니다! 따라서 목록을 다시 변경합니다.

/*you don't want to replace Salad, you want to add this new fancy 0
  position to your list. It wasn't there before so you can either define it*/
myDietFavorites[0] = "Pizza";

/*or Add it*/
myDietFavorites.Add(0, "Pizza");

정의에는 두 가지 가능성이 있습니다. 이전에 존재하지 않았던 것에 대한 새로운 정의를 제공하거나 이미 존재하는 정의를 변경하려는 것입니다.

Add 메서드를 사용하면 레코드를 추가 할 수 있지만 한 가지 조건에서만이 정의에 대한 키가 사전에 없을 수 있습니다.

이제 우리는 내부를 살펴볼 것입니다. 사전을 만들 때 컴파일러는 버킷을 예약합니다 (레코드를 저장할 메모리 공간). 버킷은 사용자가 정의하는 방식으로 키를 저장하지 않습니다. 각 키는 버킷 (Microsoft에서 정의)으로 이동하기 전에 해시되며 값 부분은 변경되지 않습니다.

예제를 단순화하기 위해 CRC32 해싱 알고리즘을 사용하겠습니다. 정의 할 때 :

myDietFavorites[0] = "Pizza";

버킷으로 이동하는 것은 db2dc565 “Pizza”(간체)입니다.

다음을 사용하여 값을 변경할 때 :

myDietFavorites[0] = "Spaghetti";

다시 db2dc565 인 0을 해시합니다. 한 다음 버킷에서이 값을 찾아 거기에 있는지 확인합니다. 거기에 있다면 키에 할당 된 값을 다시 작성하면됩니다. 그것이 없으면 버킷에 값을 넣을 것입니다.

다음과 같이 사전에서 Add 함수를 호출 할 때 :

myDietFavorite.Add(0, "Chocolate");

0을 해시하여 값을 버킷의 값과 비교합니다. 버킷이 없는 경우에만 버킷에 넣을 수 있습니다 .

특히 문자열 사전이나 문자 유형의 키로 작업하는 경우 작동 방식을 아는 것이 중요합니다. 해싱이 진행되기 때문에 대소 문자를 구분합니다. 예를 들어 “name”! = “Name”. 이것을 묘사하기 위해 우리의 CRC32를 사용합시다.

“이름”
값 : e04112b1 “이름”값 : 1107fb5b


답변

예, 이것이 차이점입니다. 키가 이미 존재하는 경우 Add 메서드는 예외를 throw합니다.

Add 메서드를 사용하는 이유는 바로 이것입니다. 사전에 이미 키가 포함되어 있지 않은 경우 일반적으로 문제를 인식 할 수 있도록 예외를 원합니다.


답변

성능면에서 가능한 유사점보다 더 정확하고 가독성이 높은 코드를 사용하십시오.

나는 추가를 설명하는 작업을 느낍니다. 키의 존재는 이미 정말 드문 예외이므로 추가로 가장 잘 표현됩니다. 의미 론적으로 더 의미가 있습니다.

dict[key] = value더 나은 대체를 나타냅니다. 이 코드가 보이면 어쨌든 키가 이미 사전에있을 것으로 예상합니다.


답변

하나는 값을 할당하고 다른 하나는 새 키와 값을 사전에 추가하는 것입니다.