Phương thức Stack.Clone() trong C# được dùng để tạo một bản sao nông (shallow copy) của Stack. Bản sao chứa các tham chiếu đến cùng các đối tượng với Stack gốc (đối với reference type) hoặc bản sao giá trị (value type).
Cú pháp
public virtual object Clone();
Trả về: object (cần ép kiểu về Stack hoặc Stack<T>).
Ví dụ 1: Clone Stack<int> (value type)
using System;
using System.Collections.Generic;
public class Demo
{
public static void Main()
{
Stack stack = new Stack();
stack.Push(150);
stack.Push(300);
stack.Push(500);
stack.Push(750);
stack.Push(1000);
stack.Push(1250);
stack.Push(1500);
stack.Push(2000);
stack.Push(2500);
Console.WriteLine("Stack gốc...");
foreach (int val in stack)
{
Console.WriteLine(val);
}
Console.WriteLine("Số lượng = " + stack.Count);
stack.Push(3000);
stack.Push(3500);
stack.Push(4000);
Console.WriteLine("\nStack gốc sau Push thêm...");
foreach (int val in stack)
{
Console.WriteLine(val);
}
Console.WriteLine("\nSố lượng (cập nhật) = " + stack.Count);
// Clone
Stack stack2 = new Stack(stack); // Copy constructor (khuyên dùng)
// Hoặc: Stack stack2 = (Stack)stack.Clone();
Console.WriteLine("\nStack cloned...");
foreach (int val in stack2)
{
Console.WriteLine(val);
}
Console.WriteLine("Số lượng cloned = " + stack2.Count);
}
}
Kết quả
Stack gốc... 2500 2000 1500 1250 1000 750 500 300 150 Số lượng = 9 Stack gốc sau Push thêm... 4000 3500 3000 2500 2000 1500 1250 1000 750 500 300 150 Số lượng (cập nhật) = 12 Stack cloned... 4000 3500 3000 2500 2000 1500 1250 1000 750 500 300 150 Số lượng cloned = 12
Ví dụ 2: Clone Stack<string> (reference type)
using System;
using System.Collections.Generic;
public class Demo
{
public static void Main()
{
Stack stack = new Stack();
stack.Push("Inspiron");
stack.Push("Alienware");
stack.Push("Projectors");
stack.Push("Monitors");
stack.Push("XPS");
stack.Push("Laptop");
stack.Push("Notebook");
Console.WriteLine("Stack gốc...");
foreach (string val in stack)
{
Console.WriteLine(val);
}
Console.WriteLine("Số lượng = " + stack.Count);
stack.Push("Headphone");
stack.Push("Keyboard");
stack.Push("Earphone");
Console.WriteLine("\nStack gốc sau Push thêm...");
foreach (string val in stack)
{
Console.WriteLine(val);
}
Console.WriteLine("Số lượng (cập nhật) = " + stack.Count);
// Clone qua copy constructor
Stack stack2 = new Stack(stack);
Console.WriteLine("\nStack cloned...");
foreach (string val in stack2)
{
Console.WriteLine(val);
}
Console.WriteLine("Số lượng cloned = " + stack2.Count);
}
}
Kết quả
Stack gốc... Notebook Laptop XPS Monitors Projectors Alienware Inspiron Số lượng = 7 Stack gốc sau Push thêm... Earphone Keyboard Headphone Notebook Laptop XPS Monitors Projectors Alienware Inspiron Số lượng (cập nhật) = 10 Stack cloned... Earphone Keyboard Headphone Notebook Laptop XPS Monitors Projectors Alienware Inspiron Số lượng cloned = 10
Shallow Copy vs Deep Copy
| Loại | Value Type (int, struct...) | Reference Type (class, string...) |
|---|---|---|
| Shallow Copy (Clone) | Copy giá trị thực sự | Copy tham chiếu (trỏ cùng object) |
| Deep Copy | Copy giá trị | Tạo object mới, copy toàn bộ dữ liệu |
Với string (immutable), shallow copy an toàn như deep copy vì không thể sửa đổi string hiện có.
Clone() vs Copy Constructor vs ToArray()
| Cách | Cú pháp | Ưu điểm |
|---|---|---|
| Clone() | (Stack<T>)stack.Clone() |
Polymorphic, dùng cho non-generic Stack |
| Copy Constructor | new Stack<T>(stack) |
Khuyên dùng: an toàn kiểu, rõ ràng, hiệu suất tốt |
| ToArray() | stack.ToArray() |
Trả về mảng, linh hoạt dùng LINQ |
Lưu ý
- Clone() trả về
object, cần ép kiểu (unboxing cho non-generic). - Generic
Stack<T>không override Clone() (kế thừa từ non-generic), nên vẫn trả về object. - Sau Clone, thay đổi Stack gốc (Push/Pop/Clear) không ảnh hưởng Stack cloned.
- Nhưng thay đổi nội dung object reference type bên trong (nếu mutable) sẽ ảnh hưởng lẫn nhau.