string ב-C# הוא רצף של תווי UTF-16 (ערכי char). זה טיפוס הפניה, אבל הוא מתנהג כמו ערך בדרכים שחשובות: הוא בלתי ניתן לשינוי, ו-== משווה את הטקסט ולא את זהות האובייקט. string היא מילת המפתח של C# לטיפוס System.String של .NET; אפשר להחליף ביניהן בחופשיות.
פלט:
Porto
5
0
*****
hi
Porto has 5 letters
מחרוזות הן בלתי ניתנות לשינוי
אף מתודה לא משנה מחרוזת במקום. ToUpper, Replace, Trim וכל מתודה אחרת מחזירות מחרוזת חדשה ולא נוגעות במקור. שכחה להשתמש בערך המוחזר היא באג מחרוזות נפוץ מאוד:
פלט:
[ maya ]
[MAYA]
tea
tea and cake
אי-השינוי הופך מחרוזות לבטוחות לשיתוף בין תהליכונים ולשימוש כמפתחות במילון. המחיר הוא שבניית מחרוזת חלק אחר חלק בלולאה יוצרת מחרוזת חדשה בכל צעד; לשם כך השתמשו ב-StringBuilder.
Length ואינדקסים
Length הוא מאפיין (בלי סוגריים). האינדקסר s[i] מחזיר את ה-char במיקום i, בספירה מ-0, והוא לקריאה בלבד:
פלט:
7
A
1
IndexOutOfRangeException
XB-2931
C# 8 ומעלה מקבלות גם אינדקס מהסוף: code[^1] הוא התו האחרון, כמו code[code.Length - 1]. כדי לקחת כמה תווים בבת אחת, ראו substring.
Length סופר יחידות קוד של UTF-16, לא את מה שקורא רואה כתווים. רוב האותיות ברוב השפות הן יחידה אחת, אבל אמוג'י וכמה כתבים נדירים משתמשים בשתיים (זוג surrogate), ולכן "👍".Length הוא 2.
השוואת מחרוזות
== ו-!= משווים את התווים, בתלות באותיות גדולות וקטנות. לכל דבר אחר, העבירו ערך StringComparison שמגדיר איך להשוות:
פלט:
False
False
True
True
apple first
True
False
False
True
באיזו השוואה להשתמש:
Ordinalמשווה את הקודים המספריים של התווים. היא מהירה, צפויה וזהה בכל מחשב. השתמשו בה למזהים, שמות קבצים, מפתחות, ערכי פרוטוקול וכל דבר שלא מוצג לאדם.OrdinalIgnoreCaseזהה, אבל מתעלמת מאותיות גדולות וקטנות. הבחירה הנכונה לבדיקות בלי תלות באותיות גדולות וקטנות, כמו סיומות קבצים או כותרות HTTP.CurrentCulture(ו-CurrentCultureIgnoreCase) פועלת לפי הכללים של השפה של המשתמש, כך שהיא ממיינת מילים כמו שמילון בשפה הזו היה ממיין. השתמשו בה למיון רשימות שמוצגות למשתמשים.InvariantCultureמשתמשת בכללים שתלויים בתרבות אבל לא בהגדרות השפה של המשתמש. היא עדיין תלויה בספריית הגלובליזציה: .NET מודרני משתמש ב-ICU, .NET Framework משתמש ב-NLS של Windows, והשתיים יכולות לסדר חלק מהמחרוזות בצורה שונה.
string.Compare(a, b) ו-a.CompareTo(b) בלי StringComparison משתמשות בתרבות הנוכחית, ולכן התוצאות שלהן משתנות בין מחשבים. הימנעו מהשוואה עם a.ToLower() == b.ToLower(): היא מקצה שתי מחרוזות חדשות, ונותנת תשובות שגויות בחלק מהתרבויות (ה-i עם הנקודה ובלי הנקודה בטורקית הוא המקרה הקלאסי).
קריאה ל-a.Equals(b) כש-a הוא null זורקת NullReferenceException, בעוד ש-a == b וה-string.Equals(a, b) הסטטית מטפלות ב-null בבטחה.
תווי בריחה
בתוך ליטרל מחרוזת רגיל, לוכסן הפוך מתחיל רצף בריחה:
| בריחה | משמעות |
|---|---|
\n | שורה חדשה (line feed) |
\r | חזרת גררה (carriage return) |
\t | טאב |
\\ | לוכסן הפוך |
\" | מירכאה כפולה |
\' | מירכאה בודדת (נחוצה רק בליטרל char) |
\0 | תו null |
\uXXXX | תו UTF-16 לפי קוד הקסדצימלי בן 4 ספרות, למשל \u00e9 |
\U0001F44D | תו לפי קוד הקסדצימלי בן 8 ספרות; מעל U+FFFF הוא הופך לשני ערכי char |
\xH עד \xHHHH | תו לפי 1 עד 4 ספרות הקסדצימליות (עדיף להימנע: האורך דו-משמעי) |
\a, \b, \f, \v | התראה, backspace, form feed, טאב אנכי |
\e | תו escape, U+001B (C# 13) |
פלט:
Name: Ana
City: Porto
She said "hi"
C:\temp\report.txt
cafe = cafe
' is a quote char
רצף לא מוכר כמו "\d" הוא שגיאת קומפילציה (CS1009, רצף בריחה לא מזוהה), וזה מה שקורה כשנתיב של Windows או ביטוי רגולרי נכתבים כמחרוזת רגילה.
מחרוזות verbatim ומחרוזות מרובות שורות
הוספת @ לפני ליטרל הופכת אותו ל-verbatim: לוכסנים הפוכים הם תווים רגילים, והמחרוזת יכולה להתפרס על כמה שורות. הבריחה היחידה שנשארת היא "", שמייצרת מירכאה כפולה אחת.
פלט:
C:\Users\ana\Documents\notes.txt
\d{3}-\d{4}
He said "ready" and left.
Rua das Flores 12
4050-262 Porto
Portugal
first line
second line
מחרוזת verbatim מרובת שורות כוללת את כל מה שבין המירכאות, כולל ההזחה של שורות ההמשך, ולכן כותבים אותן בדרך כלל צמוד לשוליים כמו בדוגמה. מעברי השורה שהיא מכילה הם אלה שבקובץ המקור, כך שקובץ שנשמר עם סופי שורה של Windows מייצר \r\n.
C# 11 הוסיפה raw string literals, שפותרים את שתי הבעיות. הם מתחילים ומסתיימים בשלוש מירכאות כפולות או יותר, לא צריכים שום בריחה, ומסירים את ההזחה שבה מוזחות המירכאות הסוגרות:
// C# 11 and later
string json = """
{
"name": "Ana",
"path": "C:\temp"
}
""";
// The 4 spaces before the closing """ are removed from every line.
אם התוכן עצמו מכיל """, התחילו וסיימו עם ארבע מירכאות. ליטרלים גולמיים משתלבים גם עם אינטרפולציה ($"""..."""); ראו אינטרפולציית מחרוזות.
null, מחרוזת ריקה ורווח לבן
משתנה מחרוזת יכול להיות null (אין מחרוזת בכלל), ריק ("", אורך 0), או להכיל רק רווח לבן. שתי מתודות עזר סטטיות בודקות את המקרים האלה בלי סיכון ל-NullReferenceException:
פלט:
null empty: True blank: True
"" empty: True blank: True
" " empty: False blank: True
"Ana" empty: False blank: False
True
לבדיקת קלט של משתמש, string.IsNullOrWhiteSpace היא כמעט תמיד מה שצריך. string.Empty ו-"" הם אותו ערך; מה לכתוב זה עניין של סגנון.
מעבר על תווים בלולאה
מחרוזת היא אוסף שאפשר לעבור עליו, כך ש-foreach מבקרת בכל char. לטיפוס char יש מתודות סטטיות לסיווג תווים:
פלט:
letters=6 digits=4 upper=1 symbols=1
!6202tesnuS
חיבור מחרוזות
+ משרשר, ועובד עם כל טיפוס בצד השני (הוא קורא ל-ToString()). לשילוב של הרבה ערכים, העדיפו אינטרפולציה או string.Join:
פלט:
Ana Silva, 31
Ana Silva, 31
AnaSilva
tea | coffee | juice
Total: 23
Total: 5
שתי השורות האחרונות מראות מלכודת של קדימות אופרטורים: + מחושב משמאל לימין, כך שברגע שהצד השמאלי הוא מחרוזת, כל + שבא אחריו הוא שרשור. שימו סוגריים סביב חישובים בתוך שרשור.
שאלות נפוצות
איך מקבלים את האורך של מחרוזת ב-C#?
משתמשים במאפיין Length: "hello".Length הוא 5. זה מאפיין, לא מתודה, ולכן אין סוגריים. Length סופר יחידות קוד של UTF-16, כך שאמוג'י או תו אחר מחוץ ל-Basic Multilingual Plane נספר כ-2. קריאה אליו על מחרוזת null זורקת NullReferenceException.
איך משווים מחרוזות ב-C#?
a == b משווה את הטקסט ותלוי באותיות גדולות וקטנות. לשוויון בלי תלות באותיות גדולות וקטנות השתמשו ב-string.Equals(a, b, StringComparison.OrdinalIgnoreCase). כדי למיין או לסדר מחרוזות השתמשו ב-string.Compare(a, b, StringComparison.Ordinal) או בהשוואה שתלויה בתרבות, שמחזירה מספר שלילי, אפס או מספר חיובי.
איך כותבים מחרוזת מרובת שורות ב-C#?
הוסיפו @ לפני הליטרל כדי להפוך אותו ל-verbatim: הוא יכול להתפרס על כמה שורות, לוכסנים הפוכים הם תווים רגילים, ומירכאה כפולה נכתבת כ-"". ב-C# 11 ומעלה, גם raw string literals שתחומים ב-""" מתפרסים על כמה שורות, מסירים את ההזחה המשותפת ולא צריכים שום בריחה. אפשר גם לחבר שורות עם \n או Environment.NewLine.
מה זו מחרוזת verbatim ב-C#?
ליטרל מחרוזת עם הקידומת @, כמו @"C:\Users\ana". רצפי בריחה לא מעובדים, כך שלוכסן הפוך הוא פשוט לוכסן הפוך, ולכן זו הבחירה הטבעית לנתיבים של Windows ולביטויים רגולריים. הבריחה היחידה בתוכה היא "" עבור מירכאה כפולה.
מה ההבדל בין string ל-String ב-C#?
אין הבדל. string הוא מילת המפתח של C# שמשמשת כינוי לטיפוס System.String של .NET, בדיוק כמו ש-int הוא כינוי ל-System.Int32. המוסכמה היא להשתמש ב-string בהצהרות וב-string.IsNullOrEmpty(...) בקריאות סטטיות, אבל שתי הצורות מתקמפלות בדיוק לאותו דבר.
באילו תווי בריחה C# תומכת?
\n שורה חדשה, \r חזרת גררה, \t טאב, \\ לוכסן הפוך, \" מירכאה כפולה, \' מירכאה בודדת, \0 תו null, \uXXXX תו UTF-16 לפי קוד הקסדצימלי, \U0001F600 תו לפי קוד בן 8 ספרות (הוא הופך לזוג surrogate), \a התראה, \b backspace, \f form feed, \v טאב אנכי, ו-\e (C# 13) escape. רצף לא מוכר כמו \d הוא שגיאת קומפילציה (CS1009), ולכן ביטויים רגולריים נכתבים בדרך כלל כמחרוזות verbatim.