בחינת חריגות ותהליך הטיפול בחריגים
- 11 דקות
שגיאות זמן ריצה ביישום C# מנוהלות באמצעות מנגנון הנקרא חריגים. חריגים מספקים דרך מובנית, אחידה ובטוחה לטיפול הן ברמת המערכת והן בתנאים של שגיאות ברמת היישום. חריגים נוצרים על-ידי זמן הריצה של .NET או על-ידי הקוד ביישום.
תרחישים נפוצים הדורשים טיפול בחריגים
קיימים כמה תרחישי תיכנות המחייבים טיפול בחריגים. רבים מתרחישים אלה כוללים צורה מסוימת של רכישת נתונים. על אף שחלק מהתרחישים כרוכים בטכניקות קידוד הנמצאות מחוץ לטווח של הדרכה זו, עדיין כדאי תצוין.
תרחישים נפוצים הדורשים טיפול בחריגים כוללים:
קלט משתמש: חריגים יכולים להתרחש כאשר קוד מעבד קלט של משתמש. לדוגמה, חריגים מתרחשים כאשר ערך הקלט הוא בתבנית שגויה או מחוץ לטווח.
עיבוד נתונים וחישובים: חריגים יכולים להתרחש כאשר קוד מבצע חישובי נתונים או המרות. לדוגמה, חריגים מתרחשים כאשר קוד מנסה לחלק באפס, לשדר לסוג שאינו נתמך או להקצות ערך מחוץ לטווח.
פעולות קלט/פלט של קובץ: חריגות עשויות להתרחש כאשר קוד קורא מקובץ או כותב לקובץ. לדוגמה, חריגים מתרחשים כאשר הקובץ אינו קיים, לתוכנית אין הרשאת גישה לקובץ או שהקובץ נמצא בשימוש על-ידי תהליך אחר.
פעולות מסד נתונים: חריגים יכולים להתרחש כאשר קוד מקיים אינטראקציה עם מסד נתונים. לדוגמה, חריגים מתרחשים כאשר חיבור מסד הנתונים אובד, שגיאת תחביר מתרחשת במשפט SQL או שמתרחשת הפרת אילוץ.
תקשורת רשת: חריגות עלולות להתרחש כאשר קוד מקיים תקשורת ברשת. לדוגמה, חריגים מתרחשים כאשר חיבור הרשת אובד, מתרחש זמן קצוב או שהשרת המרוחק מחזיר שגיאה.
משאבים חיצוניים אחרים: חריגים יכולים להתרחש כאשר קוד מקיים תקשורת עם משאבים חיצוניים אחרים. שירותי אינטרנט, ממשקי REST API או ספריות של ספקים חיצוניים יכולים להציג חריגים מסיבות שונות. לדוגמה, חריגים מתרחשים עקב בעיות בחיבורי רשת, נתונים פגומים וכו'.
מילות מפתח, בלוקי קוד ותבניות לטיפול בחריגות
טיפול בחריגים ב- C# מיושם באמצעות try, catch, ומילות finally המפתח. לכל אחת במילות מפתח אלה יש בלוק קוד משויך ובאפשרותך להשתמש בו כדי לספק מטרה ספציפית בגישה שלך לטיפול בחריגים. לדוגמה:
try
{
// try code block - code that may generate an exception
}
catch
{
// catch code block - code to handle an exception
}
finally
{
// finally code block - code to clean up resources
}
הערה
שפת C# גם מאפשרת לקוד שלך ליצור אובייקט חריגה באמצעות מילת throw המפתח. תרחישי טיפול בחריגה הכוללים שימוש throw במילת המפתח ליצירת חריגים מכוסים במודול נפרד ב- Microsoft Learn.
בלוק try הקוד מכיל את הקוד המשומר שעשוי לגרום לחריגה. אם הקוד בתוך בלוק גורם try לחריגה, החריגה מטופלת על-ידי בלוק catch תואם.
בלוק catch הקוד מכיל את הקוד המופעל כאשר חריגה נתפסת. הבלוק catch יכול לטפל בחריגה, לרשום אותו או להתעלם ממנו. ניתן catch להגדיר בלוק להפעלה כאשר מתרחש סוג חריגה כלשהו, או רק כאשר מתרחש סוג ספציפי של חריגה.
בלוק finally הקוד מכיל קוד שמבצע אם מתרחשת חריגה או לא. הבלוק finally משמש לעתים קרובות לניקוי משאבים המוקצים בבלוק try . לדוגמה, ודא שהוקצה למשתנה את הערך הנכון או הנדרש.
טיפול בחריגים ביישום C# מיושם בדרך כלל באמצעות אחד או יותר מהתבניות הבאות:
- התבנית
try-catchמורכבת מבלוק ואחריוtryמשפט אחד אוcatchיותר. כלcatchבלוק משמש לציון מטפלים עבור חריגים שונים. - התבנית
try-finallyמורכבת מבלוקtryואחריוfinallyבלוק. בדרך כלל, המשפטים של בלוקfinallyפועלים כאשר הפקד עוזב משפטtry. - התבנית
try-catch-finallyמיישמת את כל שלושת הסוגים של בלוקים לטיפול בחריגים. תרחיש נפוץtry-catch-finallytryעבור התבנית הוא כאשר משאבים מתקבלים ומשמשים בבלוק,catchנסיבות יוצאות דופן מנוהלות בבלוק, והמשאבים מופצים או מנוהלים בצורה אחרת בבלוקfinally.
כיצד חריגים מיוצגים בקוד?
חריגים מיוצגים בקוד אובייקטים, כלומר הם מופע של מחלקה. ספריית המחלקות של .NET מספקת מחלקות חריגות שהגישה אליהם היא בקוד, בדיוק כמו במחלקות NET אחרות. דוגמה נוספת של מחלקת .NET המשמשת אובייקט Random בקוד היא המחלקה (משמשת ליצירת מספרים אקראיים).
בצורה מדויקת יותר, חריגים הם סוגים, המיוצגים על-ידי כיתות שבסופו של דבר נגזרות מ- System.Exception. מחלקת חריגה הנגזרת מכוללת Exception מידע המזהה את סוג החריגה ומ מכילה מאפיינים המספקים פרטים אודות החריגה. בדיקה מפורטת יותר של הכיתה Exception נכללת בהמשך מודול זה.
מופע זמן ריצה של מחלקה נקרא בדרך כלל אובייקט, ולכן חריגים נקראים לעתים קרובות אובייקטי חריגה.
הערה
למרות שלפעמים משתמשים בהן לחילופין, מחלקה ואובייקט הם דברים שונים. מחלקה מגדירה סוג של אובייקט, אך היא אינה אובייקט עצמו. אובייקט הוא ישות מוחשית המבוססת על מחלקה.
תהליך טיפול בחריגים
כאשר מתרחשת חריגה, זמן הריצה של .NET מחפש את המשפט הקרוב ביותר catch המטפל בחריגה. התהליך מתחיל בפעולת השירות שגרמה להזרקה של החריגה. תחילה, השיטה נבדקת כדי לראות אם הקוד שגרם לחריגה נמצא בתוך בלוק try קוד. אם הקוד נמצא בתוך בלוק try קוד, המשפטים catch המשויכים לפסוקית try נחשבים לפי הסדר. אם לפסוקיות catch אין אפשרות לטפל בחריגה, מתבצע חיפוש בפעולת השירות שנקראת פעולת השירות הנוכחית. שיטה זו נבדקת כדי לקבוע אם קריאה לפעולת השירות (לשיטה הראשונה) נמצאת בתוך בלוק try קוד. אם השיחה נמצאת בתוך בלוק קוד try , הפסוקיות המשויכות catch נחשבות. תהליך חיפוש זה ממשיך עד שנמצא catch פסוקית ה יכולה לטפל בחריגה הנוכחית.
לאחר שנמצא catch פסוקית ה יכולה לטפל בחריגה, זמן הריצה מתכונן להעברת השליטה אל המשפט הראשון של הבלוק catch . עם זאת, לפני תחילת הביצוע catch של הבלוק, finallytry זמן הריצה מפעיל את כל הבלוקים המשויכים במשפטים שנמצאו במהלך החיפוש. אם נמצאה יותר finally מבלוק אחד, הם מבוצעים לפי הסדר, החל מהבלוק הקרוב ביותר לקוד שגרם להזרקה של החריגה.
אם לא catch נמצא משפט לטיפול בחריגה, זמן הריצה מסיים את היישום ומציג הודעת שגיאה למשתמש.
שקול את דוגמת הקוד הבאה הכוללת try-finally תבנית המקוננת בתוך try-catch תבנית:
try
{
// Step 1: code execution begins
try
{
// Step 2: an exception occurs here
}
finally
{
// Step 4: the system executes the finally code block associated with the try statement where the exception occurred
}
}
catch // Step 3: the system finds a catch clause that can handle the exception
{
// Step 5: the system transfers control to the first line of the catch code block
}
בדוגמה זו, התהליך הבא מתרחש:
- הביצוע מתחיל בבלוק הקוד של המשפט היוצא
try. - אירעה חריגה בבלוק הקוד של המשפט
tryהפנימי. - זמן הריצה מוצא את
catchהמשפט המשויך להצהרהtryהיוצאת. - לפני ש- Runtime מעביר את הפקד
catchאל השורה הראשונה של בלוק הקוד,finallyהוא מבצע את המשפט המשויך להצהרה הפנימיתtry. - לאחר מכן, זמן הריצה מעביר את השליטה אל
catchהשורה הראשונה של בלוק הקוד ומבצע את הקוד המטפל בחריגה.
בדוגמה פשוטה זו, התבניות try-catchtry-finally המקוננות והתבניות שוכנות בשיטה אחת, try-catchtry-finally אך ניתן לפרוס תבניות מרובות ותבניות בין שיטות המתקשרות לשיטות אחרות.
טיפול בחריגים ומחסנית הקריאות
לעתים קרובות תראה את המונח "מערום קריאות משתחרר" כאשר אתה קורא אודות טיפול בחריגים ותהליך טיפול בחריגים. כדי להבין מונח זה, עליך להבין את ערימת הקריאות וכיצד היא משמשת למעקב אחר "ערימת קריאות פעולת השירות" במהלך ביצוע קוד.
אפשר לחשוב על ערימת הקריאות כמו מגדל של בלוקים. כאשר אתה בונה מגדל, אתה מתחיל בבלוק אחד בלבד. בכל פעם שאתה מוסיף בלוק למגדל, אתה ממקם אותו מעל הבלוקים הקיימים. כאשר היישום מתחיל לפעול במאתר הבאגים, נקודת הכניסה ליישום שלך היא השכבה הראשונה שנוספה למחסנית הקריאות (הבלוק הראשון של המגדל). בכל פעם ששיטה קוראת לשיטה אחרת, השיטה החדשה מתווספת לחלק העליון של הערימה. כאשר הקוד יוצא משיטה, פעולת השירות מוסרת ממחסנית הקריאות.
הערה
עבור יישום מסוף, נקודת הכניסה ליישום שלך היא המשפטים ברמה העליונה. במחסנית הקריאות של Visual Studio Code, נקודת כניסה זו נקראת השיטה Main .
Call stack unwinding הוא התהליך שבו משתמשת תוכנית .NET Runtime כאשר תוכנית C# נתקלה בשגיאה. זה אותו תהליך שעיין בו זה עתה.
חוזר לאנלוגיה של מגדל החסימה, כאשר אתה צריך להסיר בלוק מהמגדל, אתה מתחיל מלמעלה ומסיר כל בלוק עד שאתה מגיע לזה שאתה צריך. תהליך זה דומה לאופן שבו פועל מערום השיחות, שבו כל שכבת שיחה בערימה דומה לבלוק במגדל. כאשר זמן הריצה צריך להירגע את ערימת הקריאות, היא מתחילה מלמעלה ומסירה כל שכבת שיחה עד שהיא מגיעה לשכבה הכוללת את מה שהיא צריכה. במקרה זה, שכבת השיחה הדרושה לה היא catch השיטה הכוללת פסוקית ה יכולה לטפל בחריגה שהתרחשה.
תקציר
להלן כמה דברים חשובים שיש לזכור ביחידה זו:
- תרחישים נפוצים שעשויים לדרוש טיפול בחריגים כוללים קלט משתמש, עיבוד נתונים, פעולות קלט/O של קובץ, פעולות מסד נתונים ותקשורת רשת.
- טיפול בחריגים ב- C# מיושם באמצעות
try,catchומילותfinallyמפתח. לכל מילת מפתח יש בלוק קוד משויך המשמש מטרה ספציפית. - חריגים מיוצגים כסוגים ונגזרים מהמחלקה
System.Exceptionב- .NET. חריגים מכילים מידע המזהה את סוג החריגה ומאפיינים המספקים פרטים נוספים. - כאשר מתרחשת חריגה, זמן הריצה של .NET מחפש את המשפט הקרוב
catchביותר שניתן לטפל בו. החיפוש מתחיל בפעולת השירות שבה הוצגה החריגה, וזז כלפי מטה במחסנית הקריאות במידת הצורך.
בדוק את הידע שלך
משוב
האם עמוד זה היה מועיל?
לא
זקוק לעזרה בנושא זה?
רוצה לנסות להשתמש ב'שאל את Learn' כדי להבהיר או להדריך אותך בנושא זה?