Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

วิธีคัดลอก List ไป List อีกอันโดยไม่ใช้ foreach ใน C#

วิธีการคัดลอก List<T> ใน C# โดยไม่ต้องใช้ foreach

List<T> เป็นคอลเลกชันเจเนอริกที่เข้าถึงด้วยดัชนีได้ มีเมธอดสำหรับจัดเรียง ค้นหา และแก้ไข อยู่ในเนมสเปซ System.Collections.Generic

วิธีที่ 1: Constructor คัดลอก (Copy Constructor) - แนะนำมากที่สุด

using System;
using System.Collections.Generic;

class Program
{
    public static void Main()
    {
        List<int> originalList = new List<int> { 1, 2, 3, 4, 5, 7, 8, 9 };
        
        // สร้าง List ใหม่โดยส่ง original เข้า constructor
        List<int> copy = new List<int>(originalList);
        
        // ตรวจสอบว่าเป็นคนละ object (Shallow Copy)
        Console.WriteLine($"Same reference? {object.ReferenceEquals(originalList, copy)}");  // False
        Console.WriteLine($"Same contents? {originalList.SequenceEqual(copy)}");  // True
        
        // แก้ไข copy ไม่กระทบ original
        copy.Add(99);
        Console.WriteLine($"Original count: {originalList.Count}");  // 8
        Console.WriteLine($"Copy count: {copy.Count}");  // 9
    }
}

วิธีที่ 2: ToList() (LINQ)

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    public static void Main()
    {
        List<int> originalList = new List<int> { 1, 2, 3, 4, 5, 7, 8, 9 };
        
        // ใช้ LINQ ToList()
        List<int> copy = originalList.ToList();
        
        // เหมือน Constructor แต่อ่านง่ายกว่าในบางบริบท
        copy.Add(99);
        Console.WriteLine($"Original: {originalList.Count}, Copy: {copy.Count}");
    }
}

วิธีที่ 3: GetRange() - คัดลอกบางส่วน

using System;
using System.Collections.Generic;

class Program
{
    public static void Main()
    {
        List<int> originalList = new List<int> { 1, 2, 3, 4, 5, 7, 8, 9 };
        
        // คัดลอก 3 ตัวแรก (index 0, จำนวน 3)
        List<int> partialCopy = originalList.GetRange(0, 3);
        
        Console.WriteLine("Partial copy: " + string.Join(", ", partialCopy));  // 1, 2, 3
        
        // คัดลอกตั้งแต่ index 3 จนจบ
        List<int> fromIndex3 = originalList.GetRange(3, originalList.Count - 3);
        Console.WriteLine("From index 3: " + string.Join(", ", fromIndex3));  // 4, 5, 7, 8, 9
    }
}

วิธีที่ 4: เพิ่มทีหลังด้วย AddRange()

using System;
using System.Collections.Generic;

class Program
{
    public static void Main()
    {
        List<int> originalList = new List<int> { 1, 2, 3 };
        List<int> copy = new List<int>();  // ว่าง
        
        copy.AddRange(originalList);  // เพิ่มทีหลัง
        
        // หรือกำหนด Capacity ล่วงหน้าเพื่อประสิทธิภาพ
        List<int> copy2 = new List<int>(originalList.Count);
        copy2.AddRange(originalList);
    }
}

วิธีที่ 5: Collection Initializer (C# 3.0+)

using System;
using System.Collections.Generic;

class Program
{
    public static void Main()
    {
        List<int> originalList = new List<int> { 1, 2, 3 };
        
        // Spread operator ไม่มีใน C# ต้องทำแบบนี้
        List<int> copy = new List<int>(originalList);  // วิธีสั้นที่สุด
        
        // หรือถ้าต้องการเพิ่มค่าอื่นพร้อมกัน
        List<int> extended = new List<int>(originalList) { 4, 5, 6 };
        // ผลลัพธ์: 1, 2, 3, 4, 5, 6
    }
}

ตารางเปรียบเทียบ

วิธีSyntaxคัดลอกบางส่วนได้?ประสิทธิภาพความชัดเจน
Constructornew List<T>(original)ไม่ได้ (ต้องใช้ GetRange)ดีมากชัดเจนมาก
ToList()original.ToList()ไม่ได้ดีอ่านง่าย (LINQ style)
GetRangeoriginal.GetRange(index, count)ได้ดีชัดเจนสำหรับ subset
AddRangecopy.AddRange(original)ได้ (รวมกับ list เดิม)ดีเหมาะสำหรับ merge

Shallow Copy vs Deep Copy

ทุกวิธีข้างต้นเป็น Shallow Copy - คัดลอก reference ของ object ไป (ถ้า T เป็น reference type)

class Person { public string Name; }

var original = new List<Person> { new Person { Name = "A" } };
var copy = new List<Person>(original);  // Shallow copy

copy[0].Name = "B";
Console.WriteLine(original[0].Name);  // "B" - เปลี่ยนไปด้วย!

Deep Copy (ถ้าจำเป็น)

// 1. Manual copy
var deepCopy = original.Select(p => new Person { Name = p.Name }).ToList();

// 2. JSON serialize/deserialize (ง่ายแต่ช้า)
var json = JsonConvert.SerializeObject(original);
var deepCopy2 = JsonConvert.DeserializeObject<List<Person>>(json);

// 3. ICloneable interface (ต้อง implement เอง)

สรุปแนะนำ

  • คัดลอกทั้ง List: ใช้ new List<T>(original) - เร็วที่สุด อ่านง่าย
  • คัดลอกบางส่วน: ใช้ original.GetRange(start, count)
  • รวม List: ใช้ list1.AddRange(list2) หรือ list1.Concat(list2).ToList()
  • Deep copy: ต้องเขียนเองหรือใช้ Serialization