Hướng dẫn sử dụng C# String và StringBuilder
Công ty Vĩnh Cửu tuyển dụng lập trình viên Java

1- Sơ đồ thừa kế

Khi làm việc với các dữ liệu văn bản, CSharp cung cấp cho bạn 2 class String StringBuilder. Nếu làm việc với các dữ liệu lớn bạn nên sử dụng StringBuilder để đạt hiệu năng nhanh nhất. Về cơ bản 2 class này có nhiều điểm giống nhau.
  • String là không thể thay đổi (immutable), khái niệm này sẽ được nói chi tiết ở trong tài liệu, và không cho phép có class con.
  • StringBuilder có thể thay đổi (mutable)

2- Khái niệm mutable & immutable

Hãy xem một ví dụ minh họa:
// Đây là một class có 1 trường value.
// Sau khi khởi tạo đối tượng bạn có thể sét đặt lại giá trị của trường Value
// thông qua việc gọi method SetNewValue(int).
// Như vậy đây là class có thể thay đổi (mutable).
class MutableClassExample
{
   private int Value;

   public MutableClassExample(int value)
   {
       this.Value = value;
   }

   public void SetNewValue(int newValue)
   {
       this.Value = newValue;
   }
}

// Đây là một class với trường Value, Name.
// Khi bạn khởi tạo đối tượng class này
// bạn không thể sét đặt lại Value từ bên ngoài, và tất cả các trường khác của nó cũng thế.
// Class này không hề có các hàm để sét đặt lại các trường (field) từ bên ngoài.
// Nếu muốn bạn chỉ có thể tạo mới một đối tượng khác.
// Điều đó có nghĩa là class này là không thể thay đổi (immutable)
class ImmutableClassExample
{
   private int Value;
   private String Name;

   public ImmutableClassExample(String name, int value)
   {
       this.Value = value;
       this.Name = name;
   }

   public String GetName()
   {
       return Name;
   }

   public int GetValue()
   {
       return Value;
   }
}
 
String là một class không thể thay đổi, String có nhiều thuộc tính (trường), ví dụ length,... nhưng các giá trị đó là không thể thay đổi.

3- String và string

Trong C# đôi khi bạn thấy String và string được sử dụng song song. Thực tế chúng không có khác biệt gì, string có thể coi là một bí danh (alias) cho System.String (Tên đầy đủ bao gồm cả namespace của class String).

Bảng dưới đây mô tả danh sách đầy đủ các bí danh cho các class thông dụng.
Bí danh Class
object System.Object
string System.String
bool System.Boolean
byte System.Byte
sbyte System.SByte
short System.Int16
ushort System.UInt16
int System.Int32
uint System.UInt32
long System.Int64
ulong System.UInt64
float System.Single
double System.Double
decimal System.Decimal
char System.Char

4- String

String là một class rất quan trọng trong CSharp, và bất kỳ ai bắt đầu với CSharp đều đã sử dụng câu lệnh Console.WriteLine() để in ra một String lên màn hình Console. Nhiều người thường không hề có ý niệm rằng String là không thể thay đổi ( immutable) và là class sealed (Bị niêm phong, không cho phép có class con), tất cả các thay đổi trên String đều tạo ra một đối tượng String khác.
[SerializableAttribute]
[ComVisibleAttribute(true)]
public sealed class String : IComparable, ICloneable, IConvertible,
    IEnumerable, IComparable<string>, IEnumerable<char>, IEquatable<string>

4.1- Các method của String

Bạn có thể tra cứu các phương thức của String tại:
Dưới đây là danh sách một vài phương thức thông dụng của String.
Some String methods
public bool EndsWith(string value)

public bool EndsWith(string value, StringComparison comparisonType)

public bool Equals(string value)

public int IndexOf(char value)

public int IndexOf(char value, int startIndex)

public int IndexOf(string value, int startIndex, int count)

public int IndexOf(string value, int startIndex, StringComparison comparisonType)

public int IndexOf(string value, StringComparison comparisonType)

public string Insert(int startIndex, string value)

public int LastIndexOf(char value)

public int LastIndexOf(char value, int startIndex)

public int LastIndexOf(char value, int startIndex, int count)

public int LastIndexOf(string value)

public int LastIndexOf(string value, int startIndex)

public int LastIndexOf(string value, int startIndex, int count)

public int LastIndexOf(string value, int startIndex, int count, StringComparison comparisonType)

public int LastIndexOf(string value, int startIndex, StringComparison comparisonType)

public int LastIndexOf(string value, StringComparison comparisonType)

public int LastIndexOfAny(char[] anyOf)

public int LastIndexOfAny(char[] anyOf, int startIndex)

public int LastIndexOfAny(char[] anyOf, int startIndex, int count)

public int IndexOf(string value, int startIndex, int count, StringComparison comparisonType)

public string Replace(char oldChar, char newChar)

public string Replace(string oldValue, string newValue)

public string[] Split(params char[] separator)

public string[] Split(char[] separator, int count)

public string[] Split(char[] separator, int count, StringSplitOptions options)

public string[] Split(char[] separator, StringSplitOptions options)

public string[] Split(string[] separator, StringSplitOptions options)

public bool StartsWith(string value)

public bool StartsWith(string value, bool ignoreCase, CultureInfo culture)

public bool StartsWith(string value, StringComparison comparisonType)

public string Substring(int startIndex)

public string Substring(int startIndex, int length)

public char[] ToCharArray()

public char[] ToCharArray(int startIndex, int length)

public string ToLower()

public string ToLower(CultureInfo culture)

public string ToLowerInvariant()

public override string ToString()

public string ToUpper()

public string ToUpper(CultureInfo culture)

public string ToUpperInvariant()

public string Trim()

public string Trim(params char[] trimChars)

public string TrimEnd(params char[] trimChars)

public string TrimStart(params char[] trimChars)

 

4.1.1- Length

Length là một thuộc tính của string, nó trả về số ký tự Unicode trong string này.
LengthDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StringTutorial
{
  class LengthDemo
  {
      public static void Main(string[] args)
      {
          String str = "This is text";

          // Length là một thuộc tính của string.
          // Nó chính là độ dài của chuỗi (số ký tự của chuỗi).
          int len = str.Length;

          Console.WriteLine("String Length is : " + len);

          Console.Read();
      }
  }
}
Kết quả chạy ví dụ:

4.1.2- Concat(...)

Concat là một phương thức tĩnh dùng để nối nhiều chuỗi với nhau và trả về một String mới.
ConcatDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StringTutorial
{
    class ConcatDemo
    {
        public static void Main(string[] args)
        {
            string s1 = "One";
            string s2 = "Two";
            string s3 = "Three";

            // Giống với s1 + s2;
            string s = String.Concat(s1, s2);

            Console.WriteLine("Concat s1, s2 : " + s);

            // Giống với s1 + s2 + s3;
            s = String.Concat(s1, s2, s3);

            Console.WriteLine("Concat s1, s2, s3 : " + s);

            Console.Read();
        }
    }


}
Kết quả chạy ví dụ:

4.1.3- IndexOf(..)

IndexOf(..) là một phương thức trả về chỉ số vị trí xuất hiện lần đầu tiên một ký tự chỉ định hoặc một chuỗi con chỉ định trong chuỗi hiện tại. Có 8 phương thức IndexOf nhưng khác nhau tham số. Chỉ số được tính bắt đầu từ số 0 (Không phải 1).
IndexOfDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StringTutorial
{
   class IndexOfDemo
   {
       public static void Main(string[] args)
       {
           String str = "This is text";

 
           // Tìm vị trí xuất hiện ký tự 'i' đầu tiên.
           int idx = str.IndexOf('i'); // ==> 2
           Console.WriteLine("- IndexOf('i') = " + idx);

           // Tìm vị trí xuất hiện ký tự 'i' đầu tiên
           // tính từ chỉ số thứ 4 trở về cuối chuỗi.
           idx = str.IndexOf('i', 4); // ==> 5
           Console.WriteLine("- indexOf('i',4) = " + idx);

           // Tìm vị trí xuất hiện chuỗi con "te" đầu tiên.
           idx = str.IndexOf("te"); // ==> 8
           Console.WriteLine("- IndexOf('te') = " + idx);

           Console.Read();
       }
   }

}
Kết quả chạy ví dụ:

4.1.4- Substring(..)

SubstringDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StringTutorial
{
   class SubstringDemo
   {
       public static void Main(string[] args)
       {
           string str = "This is text";

   
           // Trả về chuỗi con từ chỉ số thứ 3 tới cuối chuỗi.
           string substr = str.Substring(3);

           Console.WriteLine("- Substring(3)=" + substr);

           // Trả về chuỗi con từ chỉ số thứ 2, và độ dài 7 ký tự
           substr = str.Substring(2, 7);

           Console.WriteLine("- Substring(2, 7) =" + substr);


           Console.Read();
       }
   }

}
Kết quả chạy ví dụ:

4.1.5- Replace(...)

Replace(..): Thay thế một chuỗi con bởi một chuỗi con khác trong string hiện tại, và trả về một chuỗi mới.
ReplaceDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StringTutorial
{
    class ReplaceDemo
    {
        public static void Main(string[] args)
        {
            String str = "This is text";

            // Thay thế hết các ký tự 'i' bởi ký tự 'x'.
            String s2 = str.Replace('i', 'x');

            Console.WriteLine("- s2=" + s2);// ==> "Thxs xs text".

          
            // Thay thế tất cả các chuỗi con "is" bởi "abc".
            String s3 = str.Replace("is", "abc");

            Console.WriteLine("- s3=" + s3);// ==> "Thabc abc text".
 
            // Thay thế chuỗi con "is" xuất hiện lần đầu bởi "abc".
            String s4 = ReplaceFirst(str, "is", "abc");

            Console.WriteLine("- s4=" + s4);// ==> "Thabc is text".

            Console.Read();
        }

        // Thay thế chuỗi con xuất hiện lần đầu tiên.
        static string ReplaceFirst(string text, string search, string replace)
        {
            int pos = text.IndexOf(search);
            if (pos < 0)
            {
                return text;
            }
            return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
        }
    }

}
Kết quả chạy ví dụ:

4.1.6- Các ví dụ khác

StringOtherDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StringTutorial
{
    class StringOtherDemo
    {
        public static void Main(string[] args)
        {
            String str = "This is text";

            Console.WriteLine("- str=" + str);

            // Trả về chuỗi chữ thường.
            String s2 = str.ToLower();

            Console.WriteLine("- s2=" + s2);

            // Trả về chuỗi chữ hoa.
            String s3 = str.ToUpper();

            Console.WriteLine("- s3=" + s3);

            // Kiểm tra xem chuỗi có bắt đầu bởi chuỗi con "This" hay không.
            bool swith = str.StartsWith("This");

            Console.WriteLine("- 'str' startsWith This ? " + swith);


            // Một String với khoảng trắng phía trước và sau.
            // \t là ký tự TAB.
            // \n là ký tự xuống dòng.
            str = " \t CSharp is hot!  \t \n ";

            Console.WriteLine("- str=" + str);

            // Trả về một String mới loại bỏ khoảng trắng ở đầu và cuối chuỗi.
            String s4 = str.Trim();

            Console.WriteLine("- s4=" + s4);

            Console.Read();
        }
    }

}
Kết quả chạy ví dụ:

5- StringBuilder

Trong C# mỗi khi bạn sửa đổi một String kết quả đều tạo ra một đối tượng String mới. Trong khi đó StringBuilder chứa trong nó một mảng các ký tự, mảng này sẽ tự động thay thế bởi một mảng lớn hơn nếu thấy cần thiết, và copy các ký tự ở mảng cũ sang. Nếu bạn phải thao tác ghép chuỗi nhiều lần thì bạn nên sử dụng StringBuilder, nó giúp làm tăng hiệu năng của chương trình. Tuy nhiên nếu chỉ ghép nối một vài chuỗi thì điều đó không cần thiết, bạn không nên lạm dụng StringBuilder trong trường hợp đó. 
StringBuilderDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StringTutorial
{
  class StringBuilderDemo
  {
      public static void Main(string[] args)
      {

          // Tạo đối tượng StringBuilder
          // Hiện tại chưa có dữ liệu trên StringBuilder.
          StringBuilder sb = new StringBuilder(10);

          // Nối thêm một chuỗi con
          sb.Append("Hello...");
          Console.WriteLine("- sb after appends a string: " + sb);

          // Nối thêm một ký tự.
          char c = '!';
          sb.Append(c);
          Console.WriteLine("- sb after appending a char: " + sb);

           // Trèn một String tại chỉ số 5.
          sb.Insert(8, " CSharp");
          Console.WriteLine("- sb after insert string: " + sb);

          // Xóa một chuỗi con bắt đầu tại chỉ số 5, với 3 ký tự.
          sb.Remove(5, 3);

          Console.WriteLine("- sb after remove: " + sb);

            // Lấy ra string trong StringBuilder.
            String s = sb.ToString();

            Console.WriteLine("- String of sb: " + s);

          Console.Read();
      }
  }

}
Kết quả chạy ví dụ: