Menu

מחרוזות ב-C#: Length, השוואה, תווי בריחה, מחרוזות verbatim ומחרוזות מרובות שורות

איך מחרוזות עובדות ב-C#: אי-שינוי, Length ואינדקסים, השוואה עם ==, Equals ו-string.Compare, תווי בריחה, מחרוזות verbatim עם @ וטקסט מרובה שורות, raw string literals, בדיקות null ומחרוזת ריקה, ומעבר על תווים בלולאה.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

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.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל