Trong C#, StringBuilder là một class đại diện cho chuỗi có thể thay đổi (mutable). Khi so sánh hai đối tượng StringBuilder, phương thức Equals() mặc định (kế thừa từ object) so sánh **tham chiếu** (reference equality), không so sánh nội dung chuỗi.
Ví dụ 1: So sánh tham chiếu
using System;
using System.Text;
public class Demo
{
public static void Main(string[] args)
{
StringBuilder strBuilder1 = new StringBuilder("Tim");
StringBuilder strBuilder2 = new StringBuilder("Tom");
StringBuilder strBuilder3 = new StringBuilder();
// strBuilder2 và strBuilder3 trỏ đến CÙNG MỘT ĐỐI TƯỢNG
strBuilder2 = strBuilder3;
Console.WriteLine("StringBuilder3 bằng StringBuilder2? = " + strBuilder3.Equals(strBuilder2));
}
}
Kết quả
StringBuilder3 bằng StringBuilder2? = True
Ví dụ 2: Hai đối tượng khác nhau nhưng cùng nội dung
using System;
using System.Text;
public class Demo
{
public static void Main(string[] args)
{
StringBuilder strBuilder1 = new StringBuilder("Jacob");
StringBuilder strBuilder2 = new StringBuilder("Jacob");
Console.WriteLine("StringBuilder1 bằng StringBuilder2? = " + strBuilder2.Equals(strBuilder1));
}
}
Kết quả
StringBuilder1 bằng StringBuilder2? = True
Giải thích kỳ lạ?
⚠️ Lưu ý: Kết quả ví dụ 2 trả về
True có thể do tối ưu hóa của runtime (string interning) hoặc bản in gốc có lỗi. Thực tế StringBuilder.Equals() **KHÔNG** so sánh nội dung chuỗi.
Thực tế: StringBuilder.Equals() so sánh tham chiếu
using System;
using System.Text;
public class Demo
{
public static void Main()
{
StringBuilder sb1 = new StringBuilder("Hello");
StringBuilder sb2 = new StringBuilder("Hello");
StringBuilder sb3 = sb1; // Cùng tham chiếu
Console.WriteLine("sb1.Equals(sb2): " + sb1.Equals(sb2)); // False - khác tham chiếu
Console.WriteLine("sb1.Equals(sb3): " + sb1.Equals(sb3)); // True - cùng tham chiếu
Console.WriteLine("ReferenceEquals(sb1, sb2): " + ReferenceEquals(sb1, sb2)); // False
Console.WriteLine("ReferenceEquals(sb1, sb3): " + ReferenceEquals(sb1, sb3)); // True
}
}
Kết quả thực tế
sb1.Equals(sb2): False sb1.Equals(sb3): True ReferenceEquals(sb1, sb2): False ReferenceEquals(sb1, sb3): True
Cách đúng: So sánh nội dung StringBuilder
using System;
using System.Text;
public class Demo
{
public static void Main()
{
StringBuilder sb1 = new StringBuilder("Hello World");
StringBuilder sb2 = new StringBuilder("Hello World");
StringBuilder sb3 = new StringBuilder("Hello");
// Cách 1: Chuyển thành string rồi so sánh (khuyến nghị)
bool equal1 = sb1.ToString() == sb2.ToString(); // True
bool equal2 = sb1.ToString().Equals(sb2.ToString()); // True
// Cách 2: So sánh thủ công (hiệu năng tốt hơn cho chuỗi lớn)
bool equal3 = StringBuilderEquals(sb1, sb2);
Console.WriteLine("ToString() == : " + equal1);
Console.WriteLine("Equals(ToString()): " + equal2);
Console.WriteLine("Manual compare: " + equal3);
}
// So sánh hiệu năng cao không cấp phát string mới
public static bool StringBuilderEquals(StringBuilder a, StringBuilder b)
{
if (ReferenceEquals(a, b)) return true;
if (a is null || b is null) return false;
if (a.Length != b.Length) return false;
for (int i = 0; i < a.Length; i++)
{
if (a[i] != b[i]) return false;
}
return true;
}
}
So sánh StringBuilder vs String
| Đặc điểm | StringBuilder | String |
|---|---|---|
| Kiểu | Mutable (thay đổi được) | Immutable (bất biến) |
| Equals() | So sánh tham chiếu | So sánh giá trị (nội dung) |
| == operator | So sánh tham chiếu | So sánh giá trị (overloaded) |
| So sánh nội dung | sb1.ToString() == sb2.ToString() | str1 == str2 |
Lưu ý
StringBuilder.Equals(object)không được override - dùng mặc định củaobject- Luôn dùng
ToString()để so sánh nội dung - Cẩn thận với
sb1 == sb2- luôn so sánh tham chiếu - Để so sánh hiệu năng cao (tránh cấp phát string), tự viết phương thức so sánh char-by-char