Bu C # sözlük başlatma nasıl doğru?


64

Aşağıdakileri tökezledim ve neden bir sözdizimi hatası oluşturmadığını merak ediyorum.

var dict = new Dictionary<string, object>
{
    ["Id"] = Guid.NewGuid(),
    ["Tribes"] = new List<int> { 4, 5 },
    ["MyA"] = new Dictionary<string, object>
    {
        ["Name"] = "Solo",
        ["Points"] = 88
    }
    ["OtherAs"] = new List<Dictionary<string, object>>
    {
        new Dictionary<string, object>
        {
            ["Points"] = 1999
        }
    }
};

"MyA" ve "OtherAs" arasında "," eksik olduğuna dikkat edin.

Karışıklık burada:

  1. Kod derlenir.
  2. Son sözlük "dict" sadece üç öğe içerir: "Id", "Tribes" ve "MyA".
  3. "MyA" dışındaki herkes için değer doğrudur,
  4. "MyA", "OtherAs" için bildirilen değeri alırken orijinal değeri yok sayılır.

Bu neden yasadışı değil? Tasarım gereği bu mu?


1
@Steve sorduğu şey bu. Ben sharplab içine bu yapıştırılan ve başlangıçta benziyor OtherAsiçine ne bir anahtar olarak ekleniyor olacağınıMyA sözlük. (Ad = Yalnız, Puanlar = 88 artı DiğerAs = Liste <Sözlük <dize, nesne >>) dışında hiçbir zaman atamaz . Bunun yerine, şu anda sadece tek Puan = 1999 girişini içeren bir dikte listesini yerleştiriyor, o MyAkişinin ait olduğunu düşündüğünü geçersiz kılıyor.
pinkfloydx33

1
İlk yorumda bağlantı yapıştırılamayacak kadar uzun. Bu gerçekten garip. sharplab.io/…
pinkfloydx33

1
Evet, LinqPad ile test ettim ve aynı sonucu aldım. Burada neler olduğundan emin değilim. Bakalım bazı C # guruları buraya ışık tutabilir mi?
Steve

1
İlk sözlüğü <string, string> and modify Points to "88" olarak değiştirirseniz, derleyici hatası alırsınız "örtülü olarak 'System.Collections.Generic.List <System.Collections.Generic.Dictionary <string, object >>' türünü 'string' olarak dönüştüremezsiniz" bu aslında cevabı bulmama yardım etti!
pinkfloydx33

2
@OlegI Ben bir derleyici hata olduğunu sanmıyorum. Yanıtlarda zaten birçok iyi açıklama yapılmıştır. Ama eğer denerseniz var test = new Dictionary<string, object> { ["Name"] = "Solo", ["Points"] = 88 }["OtherAs"] = new List<Dictionary<string, object>> { new Dictionary<string, object> { ["Points"] = 1999 } };daha fazla açıklayacağız.
MKR

Yanıtlar:


54

Eksik virgül fark yaratır. Dizinleyicinin ["OtherAs"]bu sözlüğe uygulanmasına neden olur :

new Dictionary<string, object>
{
    ["Name"] = "Solo",
    ["Points"] = 88
}

Yani aslında şöyle diyorsunuz:

new Dictionary<string, object>
{
    ["Name"] = "Solo",
    ["Points"] = 88
}["OtherAs"] = new List<Dictionary<string, object>>
{
    new Dictionary<string, object>
    {
        ["Points"] = 1999
    }
};

Bunun bir atama ifadesi ( x = y) olduğunu unutmayın. Burada xile endeksli, "Ad" ve "Nokta" ile sözlüğüdür "OtherAs"ve yolduğunu List<Dictionary<string, object>>. Bir atama ifadesi y, sözlüklerin listesi olan atanan değere ( ) göre değerlendirilir .

Bu ifadenin sonucu daha sonra "MyA" anahtarına atanır, bu yüzden "MyA" sözlükler listesine sahiptir.

Sözlüğün türünü değiştirerek bunun olduğunu doğrulayabilirsiniz x:

new Dictionary<int, object>
{
    [1] = "Solo",
    [2] = 88
}
// compiler error saying "can't convert string to int"
// so indeed this indexer is applied to the previous dictionary
["OtherAs"] = new List<Dictionary<string, object>>
{
    new Dictionary<string, object>
    {
        ["Points"] = 1999
    }
}

İşte kodunuz, ancak yeniden biçimlendirilmiş ve derleyicinin nasıl ayrıştırdığını göstermek için bazı parantezler eklenmiştir:

["MyA"] 
= 
(
    (
        new Dictionary<string, object>
        {
            ["Name"] = "Solo",
            ["Points"] = 88
        }["OtherAs"] 
    )
    = 
    (
        new List<Dictionary<string, object>>
        {
            new Dictionary<string, object>
            {
                ["Points"] = 1999
            }
        }
    )
)

1
Bu gelen Sözlüğün değer türü değişiyordu objectiçin stringbu beni benzer bir hata iletisi ve verdi aha cevabı yol açtı anı. Görünüşe göre beni yendi - Telefonumda cevap yazarak suçluyorum :-p
pinkfloydx33

19

Burada olan şey, bir sözlük oluşturup ardından dizine eklediğinizdir. Dizin oluşturucu / atama ifadesinin sonucu döndürülür ve MyAsözlük yuvasına atanan budur .

Bu:

["MyA"] = new Dictionary<string, string> 
{
   ["Name"] = "Solo",
   ["Points"] = "88" 
}
["OtherAs"] = new List<Dictionary<string, object>>
{
   new Dictionary<string, object>
   {
       ["Points"] = 1999
   }
}

Aşağıdaki psuedo koduna ayrılabilir:

var temp = new Dictionary<string, object>
{ 
   ["Name"] = "Solo", 
   ["Points"] = 88 
};
// indexed contains result of assignment
var indexed = temp["OtherAs"] = new List<Dictionary<string, object>>
{
   new Dictionary<string, object>
   {
      ["Points"] = 1999
   }
};
// value is set to result of assignment from previous step
["MyA"] = indexed;
// temp is discarded

İkinci sözlüğün dizinleyicisine atanmanın sonucu döndürülür (atama atanan / sağ taraftaki değeri döndürür) Bu sözlük yalnızca "etere kaybolan" geçici bir yereldir. Dizinleyicinin sonucu (sözlükler listesi), sonunda ana sözlüğe yerleştirilen şeydir.

Bu, objectsözlük değerlerinin türü olarak kullanılması nedeniyle düşmeyi kolaylaştıran garip bir durumdur .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.