Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Phương thức Stack.Clone() trong C#

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.