ฉันเห็นวิธีต่าง ๆ ในการทำซ้ำพจนานุกรมใน C # มีวิธีมาตรฐานหรือไม่
ฉันเห็นวิธีต่าง ๆ ในการทำซ้ำพจนานุกรมใน C # มีวิธีมาตรฐานหรือไม่
คำตอบ:
foreach(KeyValuePair<string, string> entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}var entryดีกว่าในกรณีนั้นและดังนั้นฉันจึงโหวตคำตอบนี้ในการค้นหาครั้งที่สองแทนที่จะใช้คำตอบข้างต้น
                    varเมื่อคุณไม่ทราบว่าประเภทนี้เป็นแนวปฏิบัติที่ไม่ดี
                    varทำงานเฉพาะในกรณีที่รู้ว่ารวบรวมในเวลารวบรวม ถ้า Visual Studio รู้ประเภทแล้วก็พร้อมให้คุณค้นหาเช่นกัน
                    หากคุณกำลังพยายามใช้พจนานุกรมทั่วไปใน C # เช่นคุณจะต้องใช้อาเรย์แบบเชื่อมโยงในภาษาอื่น:
foreach(var item in myDictionary)
{
  foo(item.Key);
  bar(item.Value);
}หรือถ้าคุณจำเป็นต้องทำซ้ำมากกว่าชุดของคีย์ให้ใช้
foreach(var item in myDictionary.Keys)
{
  foo(item);
}และสุดท้ายหากคุณสนใจเฉพาะค่า:
foreach(var item in myDictionary.Values)
{
  foo(item);
}(โปรดทราบว่าvarคำหลักนั้นเป็นคุณสมบัติเสริม C # 3.0 และสูงกว่าคุณยังสามารถใช้ประเภท / คีย์ที่แน่นอนได้ที่นี่)
myDictionary(ยกเว้นว่าเป็นชื่อจริงของหลักสูตร) ฉันคิดว่าการใช้ var เป็นสิ่งที่ดีเมื่อประเภทชัดเจนเช่นvar x  = "some string"แต่เมื่อไม่ชัดเจนทันทีฉันคิดว่ามันเป็นโค้ดที่ขี้เกียจที่ทำร้ายผู้อ่าน / ผู้ตรวจสอบรหัส
                    varควรใช้เท่าที่จำเป็นในความคิดของฉัน โดยเฉพาะอย่างยิ่งที่นี่ไม่สร้างสรรค์: ประเภทKeyValuePairนี้มีแนวโน้มที่เกี่ยวข้องกับคำถาม
                    varมีจุดประสงค์ที่ไม่เหมือนใครและฉันไม่เชื่อว่ามันจะเป็น 'น้ำตาล' syntactic การใช้อย่างตั้งใจเป็นวิธีการที่เหมาะสม
                    ในบางกรณีคุณอาจต้องมีตัวนับที่อาจได้รับจากการใช้งาน for-loop สำหรับการที่ LINQ ให้ElementAtซึ่งช่วยให้ต่อไปนี้:
for (int index = 0; index < dictionary.Count; index++) {
  var item = dictionary.ElementAt(index);
  var itemKey = item.Key;
  var itemValue = item.Value;
}ElementAtO (n) การดำเนินงาน?
                    .ElementAtในบริบทนี้อาจนำไปสู่ข้อบกพร่องเล็กน้อย ร้ายแรงยิ่งกว่านั้นคือประเด็นของอาร์ตูโรข้างต้น คุณจะต้องทำซ้ำdictionary.Count + 1เวลาในพจนานุกรมที่นำไปสู่ความซับซ้อน O (n ^ 2) สำหรับการดำเนินการที่ควรเป็น O (n) เท่านั้น หากคุณต้องการดัชนีจริงๆ (ถ้าคุณทำคุณอาจใช้ประเภทการรวบรวมที่ไม่ถูกต้องในตอนแรก) คุณควรทำซ้ำdictionary.Select( (kvp, idx) => new {Index = idx, kvp.Key, kvp.Value})แทนและไม่ใช้.ElementAtภายในลูป
                    ขึ้นอยู่กับว่าคุณอยู่หลังคีย์หรือค่า ...
จากDictionary(TKey, TValue)คำอธิบายคลาสMSDN :
// When you use foreach to enumerate dictionary elements,
// the elements are retrieved as KeyValuePair objects.
Console.WriteLine();
foreach( KeyValuePair<string, string> kvp in openWith )
{
    Console.WriteLine("Key = {0}, Value = {1}", 
        kvp.Key, kvp.Value);
}
// To get the values alone, use the Values property.
Dictionary<string, string>.ValueCollection valueColl =
    openWith.Values;
// The elements of the ValueCollection are strongly typed
// with the type that was specified for dictionary values.
Console.WriteLine();
foreach( string s in valueColl )
{
    Console.WriteLine("Value = {0}", s);
}
// To get the keys alone, use the Keys property.
Dictionary<string, string>.KeyCollection keyColl =
    openWith.Keys;
// The elements of the KeyCollection are strongly typed
// with the type that was specified for dictionary keys.
Console.WriteLine();
foreach( string s in keyColl )
{
    Console.WriteLine("Key = {0}", s);
}โดยทั่วไปแล้วการถามหา "วิธีที่ดีที่สุด" โดยไม่มีบริบทที่เฉพาะเจาะจงก็เหมือนกับการถาม ว่าสีใดดีที่สุด ?
มือข้างเดียวมีหลายสีและไม่มีสีที่ดีที่สุด ขึ้นอยู่กับความต้องการและบ่อยครั้งที่รสนิยมเช่นกัน
ในทางกลับกันมีหลายวิธีในการทำซ้ำพจนานุกรมใน C # และไม่มีวิธีที่ดีที่สุด ขึ้นอยู่กับความต้องการและบ่อยครั้งที่รสนิยมเช่นกัน
foreach (var kvp in items)
{
    // key is kvp.Key
    doStuff(kvp.Value)
}หากคุณต้องการเฉพาะค่า (อนุญาตให้เรียกว่าitemสามารถอ่านได้มากกว่าkvp.Value)
foreach (var item in items.Values)
{
    doStuff(item)
}โดยทั่วไปผู้เริ่มต้นจะประหลาดใจเกี่ยวกับลำดับการนับของพจนานุกรม
LINQ มีไวยากรณ์ที่กระชับที่อนุญาตให้ระบุคำสั่งซื้อ (และสิ่งอื่น ๆ อีกมากมาย) เช่น:
foreach (var kvp in items.OrderBy(kvp => kvp.Key))
{
    // key is kvp.Key
    doStuff(kvp.Value)
}คุณอาจต้องการเพียงค่าอีกครั้ง LINQ ยังให้บริการโซลูชั่นที่กระชับเพื่อ:
itemได้อ่านได้ง่ายกว่าkvp.Value)นี่มันคือ:
foreach (var item in items.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value))
{
    doStuff(item)
}มีกรณีการใช้งานจริงอีกมากมายที่คุณสามารถทำได้จากตัวอย่างเหล่านี้ หากคุณไม่ต้องการคำสั่งซื้อที่เฉพาะเจาะจงเพียงทำตาม "วิธีที่ตรงไปตรงมาที่สุด" (ดูด้านบน)!
.Valuesและไม่ใช่ประโยคที่เลือก
                    Valueฟิลด์ IOrderedEnumerable<KeyValuePair<TKey, TValue>>ชนิดที่แน่นอนผมเห็นที่นี่เป็น บางทีคุณอาจหมายถึงอย่างอื่น? คุณช่วยเขียนบรรทัดที่สมบูรณ์ที่แสดงความหมายของคุณ (และทดสอบ) ได้ไหม?
                    items.Valueเหมือนที่คุณแนะนำ ในกรณีของส่วนที่สี่ที่คุณแสดงความคิดเห็นSelect()เป็นวิธีที่ทำให้เกิดforeachการระบุโดยตรงในค่าในพจนานุกรมแทนคู่ของคีย์ - ค่า ถ้าอย่างใดที่คุณไม่ชอบSelect()ในกรณีนี้คุณอาจต้องการส่วนรหัสที่สาม จุดของส่วนที่สี่คือการแสดงว่าสามารถประมวลผลคอลเลกชันล่วงหน้าด้วย LINQ
                    .Keys.Orderby()คุณจะทำซ้ำในรายการของคีย์ ถ้านั่นคือทั้งหมดที่คุณต้องการ หากคุณต้องการค่าจากนั้นในลูปคุณจะต้องค้นหาพจนานุกรมในแต่ละคีย์เพื่อรับค่า ในหลาย ๆ สถานการณ์มันจะไม่สร้างความแตกต่างในทางปฏิบัติ ในสถานการณ์ที่มีประสิทธิภาพสูงมันจะ เช่นเดียวกับที่ฉันเขียนในตอนต้นของคำตอบ: "มีหลายวิธี (... ) และไม่มีวิธีที่ดีที่สุดมันขึ้นอยู่กับความต้องการและบ่อยครั้งเกี่ยวกับรสนิยมด้วย"
                    ฉันจะบอกว่า foreach เป็นวิธีมาตรฐานถึงแม้ว่ามันจะขึ้นอยู่กับสิ่งที่คุณกำลังมองหา
foreach(var kvp in my_dictionary) {
  ...
}นั่นคือสิ่งที่คุณกำลังมองหา?
kvpเป็นที่นิยมใช้ในการตั้งชื่ออินสแตนซ์ KeyValuePair เมื่อ iterating foreach(var kvp in myDictionary){...กว่าพจนานุกรมและโครงสร้างข้อมูลที่เกี่ยวข้อง:
                    คุณสามารถลองใช้พจนานุกรมนี้เพื่อการประมวลผลแบบมัลติเธรด
dictionary
.AsParallel()
.ForAll(pair => 
{ 
    // Process pair.Key and pair.Value here
});C # 7.0แนะนำDeconstructorsและถ้าคุณใช้ . NET Core 2.0 ขึ้นไปแอพ structKeyValuePair<>จะมีDeconstruct()ให้คุณแล้ว ดังนั้นคุณสามารถทำได้:
var dic = new Dictionary<int, string>() { { 1, "One" }, { 2, "Two" }, { 3, "Three" } };
foreach (var (key, value) in dic) {
    Console.WriteLine($"Item [{key}] = {value}");
}
//Or
foreach (var (_, value) in dic) {
    Console.WriteLine($"Item [NO_ID] = {value}");
}
//Or
foreach ((int key, string value) in dic) {
    Console.WriteLine($"Item [{key}] = {value}");
}foreach (var (key, value) in dic.Select(x => (x.Key, x.Value)))
                    ฉันขอขอบคุณคำถามนี้มีคำตอบจำนวนมากอยู่แล้ว แต่ฉันต้องการที่จะทำวิจัยเล็กน้อย
การวนซ้ำพจนานุกรมอาจช้ากว่าเมื่อเปรียบเทียบกับการวนซ้ำบางอย่างเช่นอาร์เรย์ ในการทดสอบของฉันการวนซ้ำในอาร์เรย์ใช้เวลา 0.015003 วินาทีในขณะที่การวนซ้ำในพจนานุกรม (ด้วยจำนวนองค์ประกอบเท่ากัน) ใช้เวลา 0.0365073 วินาทีนั่นคือ 2.4 เท่า! แม้ว่าฉันจะเห็นความแตกต่างที่ใหญ่กว่ามาก สำหรับการเปรียบเทียบรายการอยู่ในระหว่างเวลา 0.00215043 วินาที
อย่างไรก็ตามนั่นก็เหมือนกับการเปรียบเทียบแอปเปิ้ลกับส้ม ประเด็นของฉันคือการวนซ้ำในพจนานุกรมช้า
พจนานุกรมได้รับการปรับให้เหมาะกับการค้นหาดังนั้นเมื่อคำนึงถึงสิ่งที่ฉันได้สร้างไว้สองวิธี คนหนึ่งทำหน้าที่คนอื่น ๆ ทำซ้ำปุ่มอื่น ๆ ก็จะค้นหาขึ้นมา
public static string Normal(Dictionary<string, string> dictionary)
{
    string value;
    int count = 0;
    foreach (var kvp in dictionary)
    {
        value = kvp.Value;
        count++;
    }
    return "Normal";
}อันนี้โหลดกุญแจแล้ววนซ้ำมันแทน (ฉันลองดึงกุญแจเข้าไปในสายอักขระ [] แต่ความแตกต่างนั้นเล็กน้อยมาก
public static string Keys(Dictionary<string, string> dictionary)
{
    string value;
    int count = 0;
    foreach (var key in dictionary.Keys)
    {
        value = dictionary[key];
        count++;
    }
    return "Keys";
}ด้วยตัวอย่างนี้การทดสอบ foreach ปกติใช้เวลา 0.0310062 และรุ่นคีย์ใช้เวลา 0.2205441 การโหลดกุญแจทั้งหมดและวนซ้ำในการค้นหาทั้งหมดนั้นช้ากว่ามากอย่างเห็นได้ชัด!
สำหรับการทดสอบครั้งสุดท้ายฉันทำซ้ำอีกสิบครั้งเพื่อดูว่ามีประโยชน์กับการใช้ปุ่มที่นี่ (โดยจุดนี้ฉันแค่อยากรู้อยากเห็น):
นี่คือวิธี RunTest หากช่วยให้คุณเห็นภาพว่าเกิดอะไรขึ้น
private static string RunTest<T>(T dictionary, Func<T, string> function)
{            
    DateTime start = DateTime.Now;
    string name = null;
    for (int i = 0; i < 10; i++)
    {
        name = function(dictionary);
    }
    DateTime end = DateTime.Now;
    var duration = end.Subtract(start);
    return string.Format("{0} took {1} seconds", name, duration.TotalSeconds);
}ที่นี่การวิ่งปกติแต่ละครั้งใช้เวลา 0.2820564 วินาที (นานกว่าการทำซ้ำครั้งเดียวประมาณสิบเท่า - ตามที่คุณคาดหวัง) การวนซ้ำของคีย์ใช้เวลา 2.2249449 วินาที
แก้ไขเพื่อเพิ่ม: การ อ่านคำตอบอื่น ๆ ทำให้ฉันถามว่าจะเกิดอะไรขึ้นถ้าฉันใช้พจนานุกรมแทนพจนานุกรม ในตัวอย่างนี้อาร์เรย์ใช้เวลา 0.0120024 วินาทีรายการ 0.0185037 วินาทีและพจนานุกรม 0.0465093 วินาที มีความสมเหตุสมผลที่จะคาดหวังว่าชนิดข้อมูลจะสร้างความแตกต่างว่าพจนานุกรมจะทำงานช้าลงเท่าใด
บทสรุปของฉันคืออะไร
มีตัวเลือกมากมาย รายการโปรดส่วนตัวของฉันคือ KeyValuePair
Dictionary<string, object> myDictionary = new Dictionary<string, object>();
// Populate your dictionary here
foreach (KeyValuePair<string,object> kvp in myDictionary)
{
     // Do some interesting things
}คุณยังสามารถใช้ชุดกุญแจและค่าได้
ด้วย.NET Framework 4.7หนึ่งสามารถใช้การสลายตัว
var fruits = new Dictionary<string, int>();
...
foreach (var (fruit, number) in fruits)
{
    Console.WriteLine(fruit + ": " + number);
}ในการทำให้โค้ดนี้ใช้งานในเวอร์ชัน C # ที่ต่ำกว่าให้เพิ่มSystem.ValueTuple NuGet packageและเขียนที่ใดที่หนึ่ง
public static class MyExtensions
{
    public static void Deconstruct<T1, T2>(this KeyValuePair<T1, T2> tuple,
        out T1 key, out T2 value)
    {
        key = tuple.Key;
        value = tuple.Value;
    }
}ValueTupleในตัวมันมีให้ในรูปแบบแพ็คเกจ nuget สำหรับเวอร์ชั่นก่อนหน้านี้ ที่สำคัญกว่า, C # 7.0 ขึ้นไปเป็นสิ่งจำเป็นสำหรับDeconstructวิธีการในการทำงานเป็น Deconstructor var (fruit, number) in fruitsสำหรับ
                    ตั้งแต่ C # 7 คุณสามารถแยกโครงสร้างวัตถุเป็นตัวแปรได้ ฉันเชื่อว่านี่เป็นวิธีที่ดีที่สุดในการทำซ้ำพจนานุกรม
ตัวอย่าง:
สร้างวิธีการขยายKeyValuePair<TKey, TVal>ที่ deconstructs มัน:
public static void Deconstruct<TKey, TVal>(this KeyValuePair<TKey, TVal> pair, out TKey key, out TVal value)
{
   key = pair.Key;
   value = pair.Value;
}วนซ้ำDictionary<TKey, TVal>ในลักษณะต่อไปนี้
// Dictionary can be of any types, just using 'int' and 'string' as examples.
Dictionary<int, string> dict = new Dictionary<int, string>();
// Deconstructor gets called here.
foreach (var (key, value) in dict)
{
   Console.WriteLine($"{key} : {value}");
}คุณแนะนำด้านล่างเพื่อย้ำ
Dictionary<string,object> myDictionary = new Dictionary<string,object>();
//Populate your dictionary here
foreach (KeyValuePair<string,object> kvp in myDictionary) {
    //Do some interesting things;
}FYI foreachไม่ทำงานหากค่าเป็นประเภทวัตถุ
foreachจะไม่ทำงานหากที่คุ้มค่าเป็นประเภทobject? มิฉะนั้นสิ่งนี้ไม่สมเหตุสมผล
                    รูปแบบที่ง่ายที่สุดในการย้ำพจนานุกรม:
foreach(var item in myDictionary)
{ 
    Console.WriteLine(item.Key);
    Console.WriteLine(item.Value);
}ใช้C # 7เพิ่มวิธีการขยายนี้ไปยังโครงการใด ๆ ของการแก้ปัญหาของคุณ:
public static class IDictionaryExtensions
{
    public static IEnumerable<(TKey, TValue)> Tuples<TKey, TValue>(
        this IDictionary<TKey, TValue> dict)
    {
        foreach (KeyValuePair<TKey, TValue> kvp in dict)
            yield return (kvp.Key, kvp.Value);
    }
}
และใช้ไวยากรณ์ง่าย ๆ นี้
foreach (var(id, value) in dict.Tuples())
{
    // your code using 'id' and 'value'
}
หรืออันนี้ถ้าคุณต้องการ
foreach ((string id, object value) in dict.Tuples())
{
    // your code using 'id' and 'value'
}
ในสถานที่ดั้งเดิม
foreach (KeyValuePair<string, object> kvp in dict)
{
    string id = kvp.Key;
    object value = kvp.Value;
    // your code using 'id' and 'value'
}
วิธีการขยายเปลี่ยนส่วนที่KeyValuePairคุณIDictionary<TKey, TValue>พิมพ์เป็นอย่างมากtupleช่วยให้คุณใช้ไวยากรณ์ที่สะดวกสบายใหม่นี้
มันแปลง - เพียง - รายการพจนานุกรมที่ต้องการเป็นtuplesดังนั้นจึงไม่แปลงทั้งพจนานุกรมเป็นtuplesดังนั้นจึงไม่มีความกังวลเกี่ยวกับประสิทธิภาพที่เกี่ยวข้อง
มีค่าใช้จ่ายเพียงเล็กน้อยเท่านั้นที่เรียกวิธีการขยายสำหรับการสร้างโดยtupleเปรียบเทียบกับการใช้KeyValuePairโดยตรงซึ่งไม่ควรเป็นปัญหาหากคุณกำหนดKeyValuePairคุณสมบัติของKeyและValueตัวแปรลูปใหม่อย่างไรก็ตาม
ในทางปฏิบัติไวยากรณ์ใหม่นี้เหมาะมากสำหรับกรณีส่วนใหญ่ยกเว้นสถานการณ์จำลองประสิทธิภาพสูงพิเศษระดับต่ำซึ่งคุณยังคงมีตัวเลือกที่จะไม่ใช้ในจุดเฉพาะนั้น
ลองดูสิ: บล็อก MSDN - คุณสมบัติใหม่ใน C # 7
kvp.Keyและkvp.Valueใช้คีย์และค่าตามลำดับ ด้วย tuples คุณจะได้รับความยืดหยุ่นในการตั้งชื่อคีย์และค่าตามที่คุณต้องการโดยไม่ต้องใช้การประกาศตัวแปรเพิ่มเติมภายในบล็อก foreach เช่นคุณอาจตั้งชื่อคีย์ของคุณเป็นfactoryNameและค่าตามmodelsที่เป็นประโยชน์โดยเฉพาะอย่างยิ่งเมื่อคุณได้รับลูปซ้อน (พจนานุกรมของพจนานุกรม): การบำรุงรักษาโค้ดง่ายขึ้นมาก ลองดูสิ! ;-)
                    ฉันรู้ว่านี่เป็นคำถามที่เก่ามาก แต่ฉันสร้างวิธีการขยายที่อาจมีประโยชน์:
    public static void ForEach<T, U>(this Dictionary<T, U> d, Action<KeyValuePair<T, U>> a)
    {
        foreach (KeyValuePair<T, U> p in d) { a(p); }
    }
    public static void ForEach<T, U>(this Dictionary<T, U>.KeyCollection k, Action<T> a)
    {
        foreach (T t in k) { a(t); }
    }
    public static void ForEach<T, U>(this Dictionary<T, U>.ValueCollection v, Action<U> a)
    {
        foreach (U u in v) { a(u); }
    }ด้วยวิธีนี้ฉันสามารถเขียนรหัสเช่นนี้:
myDictionary.ForEach(pair => Console.Write($"key: {pair.Key}, value: {pair.Value}"));
myDictionary.Keys.ForEach(key => Console.Write(key););
myDictionary.Values.ForEach(value => Console.Write(value););บางครั้งหากคุณต้องการระบุค่าให้ใช้การรวบรวมค่าของพจนานุกรม:
foreach(var value in dictionary.Values)
{
    // do something with entry.Value only
}รายงานโดยโพสต์นี้ซึ่งระบุว่าเป็นวิธีที่เร็วที่สุด: http://alexpinsker.blogspot.hk/2010/02/c-fastest-way-to-iterate-over.html
ฉันพบวิธีนี้ในเอกสารสำหรับคลาส DictionaryBase บน MSDN:
foreach (DictionaryEntry de in myDictionary)
{
     //Do some stuff with de.Value or de.Key
}นี่เป็นเพียงคนเดียวที่ฉันสามารถทำงานได้อย่างถูกต้องในชั้นเรียนที่สืบทอดมาจาก DictionaryBase
Hashtableวัตถุ
                    ContainsKey()ในforรุ่น? ซึ่งเพิ่มค่าใช้จ่ายเพิ่มเติมซึ่งไม่ปรากฏในรหัสที่คุณเปรียบเทียบ TryGetValue()มีอยู่เพื่อแทนที่รูปแบบ "ถ้ามีคีย์รับรายการด้วยคีย์" นอกจากนี้หากdictมีช่วงจำนวนเต็มต่อเนื่องตั้งแต่0ถึงถึงdictCount - 1คุณจะรู้ว่าตัวทำดัชนีไม่สามารถล้มเหลวได้ มิฉะนั้นdict.Keysเป็นสิ่งที่คุณควรทำซ้ำ ไม่ว่าจะด้วยวิธีใดContainsKey()/ ไม่TryGetValue()จำเป็น สุดท้ายโปรดอย่าโพสต์ภาพหน้าจอของรหัส
                    ฉันจะใช้ประโยชน์จาก. NET 4.0 ขึ้นไปและให้คำตอบที่ปรับปรุงใหม่สำหรับคำตอบที่ได้รับการยอมรับเดิม:
foreach(var entry in MyDic)
{
    // do something with entry.Value or entry.Key
}วิธีมาตรฐานในการทำซ้ำในพจนานุกรมตามเอกสารอย่างเป็นทางการของ MSDN คือ:
foreach (DictionaryEntry entry in myDictionary)
{
     //Read entry.Key and entry.Value here
}ฉันเขียนส่วนขยายเพื่อวนลูปมากกว่าพจนานุกรม
public static class DictionaryExtension
{
    public static void ForEach<T1, T2>(this Dictionary<T1, T2> dictionary, Action<T1, T2> action) {
        foreach(KeyValuePair<T1, T2> keyValue in dictionary) {
            action(keyValue.Key, keyValue.Value);
        }
    }
}จากนั้นคุณสามารถโทร
myDictionary.ForEach((x,y) => Console.WriteLine(x + " - " + y));ForEachวิธีการที่คุณมีforeach (...) { }... ดูเหมือนว่าไม่จำเป็น
                    ถ้าพูดว่าคุณต้องการวนซ้ำคอลเลกชันค่าโดยค่าเริ่มต้นฉันเชื่อว่าคุณสามารถใช้ IEnumerable <>, โดยที่ T คือประเภทของวัตถุค่าในพจนานุกรมและ "this" เป็นพจนานุกรม
public new IEnumerator<T> GetEnumerator()
{
   return this.Values.GetEnumerator();
}แค่ต้องการเพิ่ม 2 เซ็นต์ของฉันเพราะคำตอบส่วนใหญ่เกี่ยวข้องกับ foreach-loop โปรดดูที่รหัสต่อไปนี้:
Dictionary<String, Double> myProductPrices = new Dictionary<String, Double>();
//Add some entries to the dictionary
myProductPrices.ToList().ForEach(kvP => 
{
    kvP.Value *= 1.15;
    Console.Writeline(String.Format("Product '{0}' has a new price: {1} $", kvp.Key, kvP.Value));
});สิ่งนี้เป็นการเพิ่มการเรียกเพิ่มเติมของ 'ToList ()' อาจมีการปรับปรุงประสิทธิภาพเล็กน้อย (ดังที่กล่าวไว้ที่นี่foreach กับ someList.Foreach () {} ) โดยเฉพาะเมื่อทำงานกับพจนานุกรมขนาดใหญ่และทำงานในแบบคู่ขนานไม่มี ตัวเลือก / จะไม่มีผลเลย
นอกจากนี้โปรดทราบว่าคุณจะไม่สามารถกำหนดค่าให้กับคุณสมบัติ 'ค่า' ภายใน foreach-loop ในทางกลับกันคุณจะสามารถจัดการ 'คีย์' ได้เช่นกันซึ่งอาจทำให้คุณมีปัญหาในขณะใช้งานจริง
เมื่อคุณเพียงต้องการ "อ่าน" คีย์และค่าคุณอาจใช้ IEnumerable.Select ()
var newProductPrices = myProductPrices.Select(kvp => new { Name = kvp.Key, Price = kvp.Value * 1.15 } );foreachผลข้างเคียง: บังคับให้มองเห็นผลข้างเคียงที่เกิดขึ้น
                    var dictionary = new Dictionary<string, int>
{
    { "Key", 12 }
};
var aggregateObjectCollection = dictionary.Select(
    entry => new AggregateObject(entry.Key, entry.Value));AggregateObjectเพิ่มKeyValuePair? "การทำซ้ำ" ตามที่ร้องขอในคำถามอยู่ที่ไหน
                    foreachแต่ฉันใช้มันมาก คำตอบของฉันสมควรได้รับการลงคะแนนอย่างแท้จริงหรือไม่?
                    Select ใช้การวนซ้ำเพื่อให้เกิดผลลัพธ์ แต่ไม่ใช่ตัววนซ้ำ ประเภทของสิ่งที่ย้ำ ( foreach) ใช้สำหรับ - โดยเฉพาะอย่างยิ่งการดำเนินงานที่มีผลข้างเคียง - อยู่นอกขอบเขตของ Linq Selectรวมทั้ง แลมบ์ดาจะไม่วิ่งจนกว่าaggregateObjectCollectionจะมีการแจกแจงจริง หากคำตอบนี้ถูกใช้เป็น "เส้นทางแรก" (เช่นใช้ก่อนหน้าตรงforeach) มันส่งเสริมการปฏิบัติที่ไม่ดี สถานการณ์อาจมีการดำเนินการ Linq ที่เป็นประโยชน์ก่อนทำซ้ำพจนานุกรม แต่ไม่ได้ตอบคำถามตามที่ถาม
                    พจนานุกรม <TKey, TValue>มันเป็นคลาสคอลเลกชันทั่วไปใน c # และเก็บข้อมูลในรูปแบบค่าคีย์คีย์ต้องไม่ซ้ำกันและไม่สามารถเป็น null ได้ในขณะที่ค่าสามารถซ้ำกันและเป็น null แต่ละรายการในพจนานุกรมคือ ถือว่าเป็นโครงสร้าง KeyValuePair <TKey, TValue> ซึ่งแทนค่าคีย์และค่า และด้วยเหตุนี้เราควรใช้ประเภทองค์ประกอบ KeyValuePair <TKey, TValue> ในระหว่างการวนซ้ำขององค์ประกอบ ด้านล่างเป็นตัวอย่าง
Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1,"One");
dict.Add(2,"Two");
dict.Add(3,"Three");
foreach (KeyValuePair<int, string> item in dict)
{
    Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
}ถ้าคุณต้องการใช้ลูปคุณสามารถทำได้:
var keyList=new List<string>(dictionary.Keys);
for (int i = 0; i < keyList.Count; i++)
{
   var key= keyList[i];
   var value = dictionary[key];
 }foreachวนซ้ำ   และประสิทธิภาพที่แย่ลงเพราะnew List<string>(dictionary.Keys)จะวนซ้ำdictionary.Countก่อนที่คุณจะมีโอกาสวนซ้ำด้วยตัวคุณเอง นอกเหนือจากที่ขอให้ "วิธีที่ดีที่สุด" เป็นเรื่องส่วนตัวฉันไม่เห็นว่าสิ่งนี้จะมีคุณสมบัติเป็น "วิธีที่ดีที่สุด" หรือ "วิธีมาตรฐาน" ที่คำถามนั้นถาม ถึง "ถ้าคุณต้องการใช้สำหรับลูป ... " ฉันจะตอบโต้ด้วย " ไม่ต้องใช้forลูป"
                    foreach (var pair in dictionary.ToArray()) { }ทุกครั้ง ถึงกระนั้นฉันคิดว่ามันเป็นการดีที่จะให้ความกระจ่างในคำตอบของสถานการณ์เฉพาะที่เราต้องการใช้รหัสนี้และความหมายของการทำเช่นนั้น
                    ง่ายด้วย linq
 Dictionary<int, string> dict = new Dictionary<int, string>();
 dict.Add(1, "American Ipa");
 dict.Add(2, "Weiss");
 dict.ToList().ForEach(x => Console.WriteLine($"key: {x.Key} | value: {x.Value}") );ToList()เพราะForEach()มีการกำหนดไว้ในList<>ชั้นเรียนเท่านั้น แต่ทำไมถึงทำแบบนั้นทั้งหมดแทนที่จะเป็นแค่foreach (var pair in dict) { }? ฉันจะบอกว่ามันง่ายกว่าและไม่มีนัยยะของหน่วยความจำ / ประสิทธิภาพที่เหมือนกัน คำตอบที่ถูกต้องนี้ได้เสนอไว้แล้วในคำตอบนี้จาก 3.5 ปีก่อนอย่างไรก็ตาม
                    นอกจากโพสต์อันดับสูงสุดที่มีการสนทนาระหว่างการใช้
foreach(KeyValuePair<string, string> entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}หรือ
foreach(var entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}สมบูรณ์ที่สุดคือต่อไปนี้เพราะคุณสามารถดูประเภทพจนานุกรมจากการเริ่มต้น kvp คือ KeyValuePair
var myDictionary = new Dictionary<string, string>(x);//fill dictionary with x
foreach(var kvp in myDictionary)//iterate over dictionary
{
    // do something with kvp.Value or kvp.Key
}