مقدمه

با رشته‌ها و چند مورد از ویژگی‌های آنها در فصل قبل آشنا شدیم و دیدیم که یک رشته به صورت یک دنیاله از کاراکترهای یونیکد تعریف می‌شود که با استفاده از اندیس می‌توان به هر کاراکتر دسترسی پیدا کرد. زبان C# امکانات و متدهای متنوعی برای کار با رشته‌ها فراهم کرده است. در این درس با رایج‌ترین ویژگی‌ها و متدهای کلاس String جهت مدیریت رشته‌ها آشنا می‌شویم و نحوه‌ی استفاده از هر کدام را با مثال عملی مشاهده می‌کنیم. مباحث پوشش داده شده شامل اتصال (ترکیب) رشته‌ها، استخراج زیررشته، جایگزینی بخش‌هایی از رشته، تغییر حروف به بزرگ یا کوچک، حذف فضاهای خالی، تجزیه و ترکیب رشته‌ها, جستجو و مقایسه‌ی رشته‌ها و همچنین استفاده از کلاس StringBuilder برای ساخت رشته‌های پویا است.

ترکیب و قالب‌بندی رشته‌ها

اتصال یا ترکیب رشته‌ها (String Concatenation) در C# به روش‌های مختلفی امکان‌پذیر است. ساده‌ترین روش استفاده از عملگر + است که برای چسباندن رشته‌ها به یکدیگر به کار می‌رود. برای مثال:

Copy Icon program.cs
string a = "Hello";
string b = "World";
string c = a + " " + b + "!";
Console.WriteLine(c);  // Hello World!

در مثال فوق، با استفاده از + رشته‌های a و b به همراه یک فاصله‌ی میانی و علامت ! در انتها به هم متصل شده‌اند. زبان C# عملگر + را برای نوع رشته تعریف کرده است تا انجام این عملیات را ساده‌تر کند. هر بار استفاده از + یک رشته‌ی جدید ایجاد می‌کند و رشته‌های قبلی را تغییر نمی‌دهد؛ بنابراین برای کارایی بهتر توصیه می‌شود که در صورت نیاز به انجام اتصالات مکرر (مثلاً در یک حلقه) از کلاس StringBuilder استفاده شود که در ادامه بحث خواهد شد.

روش نوین‌تر و خواناتر برای ترکیب مقادیر در یک رشته، رشته‌های قالب‌بندی‌شده (interpolated strings) است. در این روش، با قرار دادن کاراکتر $ در ابتدای یک رشته‌ی کوتیشن‌دار، می‌توان مستقیماً عبارت‌های سی‌شارپ را داخل رشته درون آکولاد {} قرار داد تا مقدار آن‌ها درج شود. این قابلیت از نسخه‌های جدیدتر C# افزوده شده و خوانایی کد را بهبود می‌بخشد. این روش را در درس نوع‌های Primitive هم دیده بودیم.

Copy Icon Program.cs
int x = 5;
string msg1 = "The value of x is: " + x; 
string msg2 = $"The value of x is {x}";
Console.WriteLine(msg1);  
Console.WriteLine(msg2);

در مثال فوق، دو رشته‌ی msg1 و msg2 در نهایت محتوای یکسانی دارند؛ اما msg2 با استفاده از رشته‌ی قالب‌بندی‌شده نوشته شده که کوتاه‌تر و قابل فهم‌تر است. درون رشته‌ی قالب‌بندی‌شده‌ی msg2 عبارت {x} درج شده که در زمان اجرا با مقدار متغیر x (که 5 است) جایگزین می‌شود.

استخراج زیررشته

برای به‌دست‌آوردن بخشی از رشته (زیررشته) از متد Substring() استفاده می‌شود. این متد دو شکل اصلی دارد: یکی با یک پارامتر که از موقعیت مشخصی تا انتهای رشته را برمی‌گرداند، و دیگری با دو پارامتر که زیررشته‌ای با طول مشخص از موقعیت آغازین تعیین‌شده استخراج می‌کند.

Copy Icon CSharp
string Substring(int startIndex)
string Substring(int startIndex, int length)

فرم اول این متد که یک پارامتر دارد، این پارامتر را به عنوان اندیس در نظر گرفته و زیررشته‌ای برمی‌گرداند که از این اندیس شروع می‌شود و تا انتهای رشته ادامه دارد.
فرم دوم که دو پارامتر دارد، پارامتر اول را به عنوان اندیس شروع و پارامتر دوم را به عنوان طول زیررشته در نظر می‌گیرد. مثال زیر را ببینید.

Copy Icon Program.cs
string message = "Hello, World!";

string end = message.Substring(7);
Console.WriteLine(end);  // => World!

string start = message.Substring(0, 5);
Console.WriteLine(start);  // => Hello

string middle = message.Substring(2, 3);
Console.WriteLine(middle);  // => llo 

جایگزینی بخش‌هایی از رشته

اگر بخواهیم بخشی از یک رشته را با مقداری دیگر جایگزین کنیم، می‌توانیم از متدی به نام Replace() استفاده کنیم. این متد دو شکل اصلی دارد که امضای آنها را در زیر می‌بینید:

Copy Icon CSharp
string Replace(string oldValue, string newValue)
string Replace(char oldChar, char newChar)

در کد زیر مثالی از هر دو فرم بالا را می‌بینید.

Copy Icon Program.cs
string sentence = "I like Java. Java is powerful.";
string result = sentence.Replace("Java", "C#");
Console.WriteLine(result);  
// =>  I like C#. C# is powerful.

string greeting = "Hello World!";
string result2 = greeting.Replace('o', '0');
Console.WriteLine(result);  
// =>  Hell0 W0rld

تغییر در بزرگی یا کوچکی حروف

برای تغییر بزرگی یا کوچکی حروف در یک رشته، می‌توان از متدهای ToUpper() و ToLower() استفاده کرد. این دو متد به ترتیب رشته را به حروف بزرگ و کوچک تبدیل می‌کنند. مثال زیر را ببینید:

Copy Icon Program.cs
string text = "Hello World!";
string upper = text.ToUpper();
string lower = text.ToLower();
Console.WriteLine(upper);  // => HELLO WORLD!
Console.WriteLine(lower);  // => hello world!

حذف فضاهای خالی از ابتدا و انتهای رشته

برای حذف فضاهای خالی (space, tab و ...) از ابتدا و انتهای یک رشته، می‌توانید از متد Trim() استفاده کنید. این متد یک نسخه‌ی جدید از رشته را برمی‌گرداند که فضاهای خالی ابتدا و انتهای آن حذف شده‌اند. همچنین متدهای TrimStart() و TrimEnd() به ترتیب فقط فضاهای خالی ابتدا یا انتهای رشته را حذف می‌کنند.

Copy Icon Program.cs
string raw = "   Hello World!   ";
string trimmed = raw.Trim();
string left = raw.TrimStart();
string right = raw.TrimEnd();
Console.WriteLine("[" + trimmed + "]");  // [Hello World!]
Console.WriteLine("[" + left + "]");     // [Hello World!   ]
Console.WriteLine("[" + right + "]");    // [   Hello World!]

همان‌طور که می‌بینید، متد Trim() هر دو سمت را پاک می‌کند، در حالی که TrimStart() فقط سمت چپ و TrimEnd() فقط سمت راست را حذف می‌کند.

تجزیه و ترکیب رشته‌ها

برای تجزیه (تقسیم) یک رشته به بخش‌های کوچکتر، معمولاً از متد Split() استفاده می‌شود. این متد یک جداکننده (delimiter) می‌گیرد و رشته را بر اساس آن به آرایه‌ای از زیررشته‌ها تقسیم می‌کند. همچنین برای ترکیب (join) آرایه‌ای از رشته‌ها به یک رشته واحد، می‌توان از متد Join() استفاده کرد.

Copy Icon Program.cs
string names = "Ali,Reza,Mina";
string[] arr = names.Split(',');
Console.WriteLine(arr[0]);  // => Ali
Console.WriteLine(arr[1]);  // => Reza
Console.WriteLine(arr[2]);  // => Mina

string joined = string.Join(" - ", arr);
Console.WriteLine(joined);  // => Ali - Reza - Mina

با آرایه‌ها در درس بعدی بیشتر آشنا خواهیم شد.

جستجو و مقایسه رشته‌ها

برای جستجو در یک رشته و مقایسه رشته‌ها، متدهای متنوعی در کلاس String وجود دارد. برای مثال، متد Contains() بررسی می‌کند که آیا یک زیررشته در رشته وجود دارد یا نه. همچنین متد StartsWith() و EndsWith() برای بررسی شروع یا پایان رشته با یک مقدار خاص به کار می‌روند. برای مقایسه دو رشته نیز می‌توان از عملگر == یا متد Equals() استفاده کرد.

Copy Icon Program.cs
string text = "Hello World!";
Console.WriteLine(text.Contains("World"));   // True
Console.WriteLine(text.StartsWith("Hello")); // True
Console.WriteLine(text.EndsWith("!"));      // True

string s1 = "test";
string s2 = "Test";
Console.WriteLine(s1 == s2);                  // False (حساس به بزرگی/کوچکی)
Console.WriteLine(s1.Equals(s2, StringComparison.OrdinalIgnoreCase)); // True

همان‌طور که می‌بینید، مقایسه رشته‌ها به صورت پیش‌فرض حساس به بزرگی و کوچکی حروف است. اگر بخواهید حساسیت به بزرگی/کوچکی را نادیده بگیرید، می‌توانید از پارامتر StringComparison.OrdinalIgnoreCase در متد Equals() استفاده کنید.

ساخت رشته‌های تغییرپذیر با کلاس StringBuilder

رشته‌ها در C# به صورت پیش‌فرض غیرقابل تغییر (immutable) هستند؛ یعنی هر بار که یک رشته را تغییر می‌دهید، یک شیء جدید ساخته می‌شود. اگر نیاز دارید رشته‌ای را به دفعات زیاد ویرایش یا به آن اضافه کنید (مثلاً در یک حلقه)، استفاده از کلاس StringBuilder بسیار کارآمدتر است.

کلاس StringBuilder در فضای نام System.Text قرار دارد و امکان ساخت رشته‌های تغییرپذیر را فراهم می‌کند. با استفاده از متدهایی مانند Append()، Insert() و Remove() می‌توانید به راحتی رشته را ویرایش کنید. در پایان، برای تبدیل به نوع string کافی است از متد ToString() استفاده نمایید.

Copy Icon Program.cs
using System.Text;

StringBuilder sb = new StringBuilder();
sb.Append("Hello");
sb.Append(" ");
sb.AppendLine("World!");
sb.Insert(0, "Say: ");

Console.WriteLine(sb.ToString()); 
// => Say: Hello World!

همان‌طور که می‌بینید، با StringBuilder می‌توانید به راحتی رشته را به دفعات ویرایش کنید بدون اینکه هر بار یک شیء جدید ساخته شود. این کار باعث افزایش سرعت و کاهش مصرف حافظه در برنامه‌های بزرگ می‌شود.