הפיצ’ר הזה עובר בין הכסאות אצל הרבה אנשים ואני חושב שיש לו שימושים מעולים אך גם שימוש לרעה שצריך להיזהר ממנו.
Tuple
קודם כל צריך לדעת מאיפה זה הגיע,
השימוש בטאפלים הביא סוג אובייקט חדש שהקל על העברת פרמטרים והחזרת מספר פרמטרים מפונקציות.
1 | public void SendData(Tuple<int,byte[]> information) |
השימוש ב-Item1 ו-Item2 מונע מאיתנו להעניק שמות אינדיקטיביים ולהבין יותר טוב את הקוד שלנו.
בדרך כלל להעברת פרמטרים תגבילו את עצמכם ל8 פרמטרים מקסימום בפונקציה,
אחרת כדאי ליצור מחלקה חדשה.
השימוש השני בו זה להעביר פרמטרים החוצה:
1 | public Tuple<int,byte[]> GenerateMessage(string header, string info) |
השימוש ב-Item1
ו-Item2
לא מספיק מובנים ובדרך כלל יכולים לגרום ליותר צרות אם נעשה שימוש נרחב.
לכאן מגיע הפיצ’ר החדש - Deconstruction.
Deconstructors
זה לא - Destructors.
הפעולה מבצעת את ההפך מבנאי - יוצר משתנים ממשתנה אחד.
1 | public (int age, string name) GetPersonInfo() |
השימוש שלהם מחזיר לנו את הטאפלים האהובים עלינו עם תחביר עוצמתי ומובן.
מה שיפה הוא שאפשר ליצור די-קונסטרקטורים משלנו למחלקות משלנו כדי להקל על חלק מהפיצול.
Class Deconstructors
1 | public class Person |
השימוש של הפיצ’ר הזה עם מתודות הרחבה (Extensions) נותן לנו את היכולת להגדיר מתודות כאלו לכל מחלקה.
1 | public static class PersonExtensions |
ניתן להרחיב מחלקות ללא שינוי המחלקה ולעזור למתכנתים להבין את הקוד יותר טוב.
בגלל זה, השימוש של זה תומך בעקרון ה-Open Close.
הקוד צריך להיות פתוח לשדרוג וסגור לשינויים.
והדבר האחרון שצריך לדעת על זה הוא שאפשר לוותר על חלק מהפרמטרים שלא צריכים:
1 | public class Dog |
מה כדאי לעשות עם הפיצ’ר הזה
- לתכנת עזרים שייעזרו לנו לפצל קוד ולהפוך אותו למובן יותר.
לכל גורם בקוד יש שם והבנה למה הוא משמש, לכן קל יותר לקרוא את הקוד.
1 | public (bool success, int value) ParseMessage(string message) |
- לבצע Refactor לקוד שמשתמש בטאפלים.
1 | public Tuple<int,string> GetInfo(Dog d) |
מה לא כדאי לעשות
לממש את הפונקציונליות בכל מחלקה
לא כל מחלקה צריכה את זה!1
2
3
4
5public class Person
{
public int Age {get; set;}
public string Name {get; set;}
}במחלקה הזו אנחנו בדרך כלל לא נצטרך Deconstructor.
להתחיל להשתמש בטאפלים במקום מחלקות משלנו.
בהתאם לסוגי המחלקות והמודלים שאנחנו יוצרים בקוד שלנו טאפלים לא אמורים להחליף את המחלקות שאנחנו יוצרים למרות הגמישות שלהם, יש להם חסרונות.
אני לא ארחיב על הנקודה הזו יותר, בC# 9.0 התווסף פיצ’ר חדש - Record Class
שכדאי להשתמש בו יותר.
אבל אם אתם מסיבה מוזרה משתמשים ב-C# 8 ומטה, אל תמהרו להשתמש בטאפל בכל מקום.
למה זה התווסף רק ב-C# 7.0?
אחת הבעיות המרכזיות של טאפלים היו בעיות הביצועים שלהם.
מכיוון שטאפל היה מחלקה יצירה של טאפל היה יוצר את האובייקט על ה-Heap.
שימוש נרחב בטאפלים היה גורם להיווצרות הרבה אובייקטים קטנים שיצרו עומס רב על ה-Garbage Collector.
החל מ-.Net 4.7 יש לנו את ה-ValueTuple
.
הטאפל הזה מוגדר כמבנה ולא כמחלקה והעתקה של הטאפל היא ע”י העתקת ערכים והיצירה שלו הוא על גבי המחסנית.
Benchmark - בדיקת ביצועים פשוטה
1 | { |
הרצה של זה ב-Debug ו-Release.
המעבד עליו רץ הקוד: Intel i7-7700HQ 2.8 Ghz.
1 | dotnet run -c "Release": |
מה שונה בקוד הזה? הקריאה ליצירת האובייקט בקוד ה-IL.
יצירת Tuple
:
1 | // [14 21 - 14 76] |
יצירת ValueTuple
:
1 | IL_004c: ldc.i4.0 |
קוד שמצריך ביצועים גבוהים בדרך כלל משתמש במבנים ולא מחלקות רגילות על מנת לצמצם את השימוש ב-Heap, בהקצאות ומחיקות.
תודה על הקריאה!