ฉันสามารถใช้ตัวเริ่มต้นการรวบรวมสำหรับรายการพจนานุกรม <TKey, TValue> ได้หรือไม่


94

ฉันต้องการใช้ตัวเริ่มต้นการรวบรวมสำหรับรหัสบิตถัดไป:

public Dictionary<int, string> GetNames()
{
    Dictionary<int, string> names = new Dictionary<int, string>();
    names.Add(1, "Adam");
    names.Add(2, "Bart");
    names.Add(3, "Charlie");
    return names;
}

โดยทั่วไปแล้วควรเป็นดังนี้:

return new Dictionary<int, string>
{ 
   1, "Adam",
   2, "Bart"
   ...

แต่ไวยากรณ์ที่ถูกต้องสำหรับสิ่งนี้คืออะไร?


ตรวจสอบโพสต์นี้: marcin-chwedczuk.github.io/…
csharpfolk


อย่าคิดว่าเป็นการหลอกลวงเพราะพวกเขากำลังถามไม่ใช่สำหรับไวยากรณ์การประกาศพจนานุกรมชวเลข แต่เป็นเพราะเหตุใดการจดชวเลขจึงไม่ทำงานในการตั้งค่า (โบราณ)
เอช.

คำตอบ:


157
var names = new Dictionary<int, string> {
  { 1, "Adam" },
  { 2, "Bart" },
  { 3, "Charlie" }
};

1
initializer ทำงานเมื่อใด มีไว้สำหรับDictionary<TKey, TValue>คลาสย่อยเท่านั้นหรือจะใช้งานได้ด้วยICollection<KeyValuePair<TKey, TValue>>?
Shimmy Weitzhandler

หลังจาก C # 3.0 คุณสามารถใช้varแทนประเภทการประกาศหรือหากออกจากประเภทการประกาศสามารถละเว้นnew Dictio...- stackoverflow.com/questions/5678216/…
drzaus

1
@drzaus: การใช้ var เป็นการฝึกที่น่าเกลียดน่าเกลียด C # เป็นภาษาที่พิมพ์อย่างรุนแรง
Nyerguds

1
@Nyerguds: อะไรนะ? varแท้จริงเป็นเพียงแค่ช่วยให้คุณประหยัดการกดแป้นพิมพ์ก็โดยปริยายพิมพ์มั่น
drzaus

4
@Nyerguds - คุณมีสิทธิ์ที่จะมีความคิดเห็นของคุณผมเดา แต่ถ้าคุณกำลังเริ่มต้นตัวแปรของคุณทันทีที่มีเป็นตัวอักษรแตกต่างระหว่างการใช้ไม่มีและการทำซ้ำตัวเองด้วยvar SomeType obj = new SomeType...และเนื่องจากคุณไม่สามารถประกาศได้var obj;โดยไม่ต้องเริ่มต้นทันทีฉันก็ไม่เห็นปัญหา จริงๆฉันพยายามเรียนรู้ แต่ฉันไม่สามารถควบคุมตำแหน่งของคุณได้
drzaus

36

ไวยากรณ์แตกต่างกันเล็กน้อย:

Dictionary<int, string> names = new Dictionary<int, string>()
{
    { 1, "Adam" },
    { 2, "Bart" }
}

โปรดทราบว่าคุณกำลังเพิ่มสิ่งที่มีค่าอย่างมีประสิทธิภาพ

ในฐานะที่เป็น sidenote: collection initializers มีอาร์กิวเมนต์ซึ่งโดยพื้นฐานแล้วเป็นอาร์กิวเมนต์ของฟังก์ชันAdd ()อะไรก็ตามที่มีประโยชน์เกี่ยวกับอาร์กิวเมนต์ประเภทเวลาคอมไพล์ นั่นคือถ้าฉันมีคอลเล็กชัน:

class FooCollection : IEnumerable
{
    public void Add(int i) ...

    public void Add(string s) ...

    public void Add(double d) ...
}

รหัสต่อไปนี้ถูกต้องตามกฎหมาย:

var foos = new FooCollection() { 1, 2, 3.14, "Hello, world!" };

คำตอบที่ดีฉันไม่รู้เรื่องนั้น! อย่างไรก็ตามโปรแกรมเริ่มต้นพจนานุกรมจะทำงานเมื่อใด เป็นเฉพาะคลาสย่อย Dictionary <TKey, TValue> เท่านั้นหรือจะใช้กับ ICollection <KeyValuePair <TKey, TValue >>
Shimmy Weitzhandler

@Shimmy Collection initializers ทำงานกับทุกสิ่งที่ใช้IEnumerable และมีAdd()วิธีการ
Anton Gogolev

@Shimmy: พจนานุกรมเป็นคอลเลกชัน
John Saunders

@JohnSaunders แต่ initializer Addพจนานุกรมรับสองพารามิเตอร์สำหรับการ
Shimmy Weitzhandler

2
@ ซิมมี่: ทำไมเรื่องนั้น? ประเด็นคือมันจะทำงานร่วมกับคลาสใดก็ได้ที่ใช้IEnumerable<T>และมีAddวิธีการ หากAddวิธีนี้ใช้พารามิเตอร์3 ตัวคุณจะต้องมีวัตถุ 3 ชิ้นในวงเล็บ
John Saunders


10

คำถามถูกแท็กc#-3.0แต่เพื่อความสมบูรณ์ฉันจะพูดถึงไวยากรณ์ใหม่ที่มีให้กับ C # 6 ในกรณีที่คุณใช้ Visual Studio 2015 (หรือ Mono 4.0):

var dictionary = new Dictionary<int, string>
{
   [1] = "Adam",
   [2] = "Bart",
   [3] = "Charlie"
};

หมายเหตุ: ไวยากรณ์เก่าที่กล่าวถึงในคำตอบอื่น ๆ ยังคงใช้งานได้หากคุณชอบสิ่งนั้นดีกว่า อีกครั้งเพื่อความสมบูรณ์นี่คือไวยากรณ์เก่า:

var dictionary = new Dictionary<int, string>
{
   { 1, "Adam" },
   { 2, "Bart" },
   { 3, "Charlie" }
};

สิ่งที่น่าสนใจอีกอย่างหนึ่งที่ควรทราบก็คือด้วยไวยากรณ์อย่างใดอย่างหนึ่งคุณสามารถปล่อยลูกน้ำตัวสุดท้ายได้หากต้องการซึ่งจะช่วยให้คัดลอก / วางบรรทัดเพิ่มเติมได้ง่ายขึ้น ตัวอย่างเช่นคอมไพล์ต่อไปนี้ใช้ได้ดี:

var dictionary = new Dictionary<int, string>
{
   [1] = "Adam",
   [2] = "Bart",
   [3] = "Charlie",
};

5

หากคุณกำลังมองหาไวยากรณ์ verbose ที่น้อยลงเล็กน้อยคุณสามารถสร้างคลาสย่อยของDictionary<string, object>(หรือประเภทใดก็ได้) ดังนี้:

public class DebugKeyValueDict : Dictionary<string, object>
{

}

จากนั้นก็เริ่มต้นเช่นนี้

var debugValues = new DebugKeyValueDict
                  {
                       { "Billing Address", billingAddress }, 
                       { "CC Last 4", card.GetLast4Digits() },
                       { "Response.Success", updateResponse.Success }
                  });

ซึ่งเทียบเท่ากับ

var debugValues = new Dictionary<string, object>
                  {
                       { "Billing Address", billingAddress }, 
                       { "CC Last 4", card.GetLast4Digits() },
                       { "Response.Success", updateResponse.Success }
                  });

ประโยชน์ที่คุณจะได้รับสิ่งที่รวบรวมทั้งหมดที่คุณอาจต้องการเช่นความสามารถในการพูด

is DebugKeyValueDict แทน is IDictionary<string, object>

หรือเปลี่ยนประเภทของคีย์หรือค่าในภายหลัง หากคุณกำลังทำสิ่งนี้ภายในหน้า cshtml ของมีดโกนมันจะดีกว่ามากที่จะดู

นอกจากนี้คุณยังสามารถเพิ่มวิธีการพิเศษให้กับคลาสนี้ได้อีกด้วยสำหรับสิ่งที่คุณต้องการ


นี่คือวิธีที่ ViewDataDictionary ทำงานใน MVC - stackoverflow.com/questions/607985/…
Simon_Weaver

ฉันทดลองใช้ประเภทเป็น 'นามแฝง' สำหรับพจนานุกรมและอาร์เรย์ที่พิมพ์โดยสันนิษฐานว่าจะปลอดภัยกว่าในโลกที่พิมพ์เพื่อใช้ประเภทที่กำหนดไว้ล่วงหน้า .. กลับกลายเป็นว่าไม่มีประโยชน์เมื่อพูดถึงชื่อสามัญและ linq
Patrick

1

ในตัวอย่างรหัสต่อไปนี้การจะเริ่มต้นกับกรณีของประเภทDictionary<TKey, TValue>StudentName

  Dictionary<int, StudentName> students = new Dictionary<int, StudentName>()
  {
      { 111, new StudentName {FirstName="Sachin", LastName="Karnik", ID=211}},
      { 112, new StudentName {FirstName="Dina", LastName="Salimzianova", ID=317}},
      { 113, new StudentName {FirstName="Andy", LastName="Ruth", ID=198}}
  };

จากmsdn


-3

ใช่เราสามารถใช้ collection initializer ในพจนานุกรมได้ถ้าเรามีพจนานุกรมแบบนี้ -

Dictionary<int,string> dict = new Dictionary<int,string>();  
            dict.Add(1,"Mohan");  
            dict.Add(2, "Kishor");  
            dict.Add(3, "Pankaj");  
            dict.Add(4, "Jeetu");

เราสามารถเริ่มต้นได้ดังต่อไปนี้

Dictionary<int,string> dict = new Dictionary<int,string>  
            {  

                {1,"Mohan" },  
                {2,"Kishor" },  
                {3,"Pankaj" },  
                {4,"Jeetu" }  

            }; 

4
มีคำตอบอื่น ๆ อีก 6 คำตอบที่แสดงวิธีการทำเช่นนี้ เราไม่ต้องการคำตอบที่ 7 ที่แสดงสิ่งเดียวกัน
Servy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.