שמות Properties כמחרוזות

August 4, 2008

no comments

ברצוננו לכתוב מתודה אשר תקבל שם קובץ חדש ורשימת קבצים בתיקייה ותחזיר שם קובץ תקין שאינו קיים בתיקייה (כמו שיצירת קובץ חדש בתיקייה תחת וינדוס יוצרת קבצים בשם “new”, “new1”, “new2” וכו’).

string GetUniqueFileName(List<File> files, string newFileName)

נוכל לכתוב מתודה אשר עוברת על רשימת הקבצים בתיקייה (List כלשהו) ומחפשת עפ”י מאפיין שם קובץ (obj.FileName) אם השם תפוס ואם כן, להוסיף לשם שהועבר איזשהו Suffix ולנסות שוב עד למציאת שם תקין.

עכשיו בואו נסבך – נניח שאנחנו רוצים עוד מתודה שכזו, הפעם על רשימה אחרת והשוואה מול מאפיין בשם אחר. חלקנו יכתוב עוד מתודה (copy&paste+שינויים קטנים), אבל יש דרך אחרת – הפיכת המתודה לגנרית (על הטיפוס המוכל ב-List) והעברת שם ה-Property כמחרוזת.

string GetUniqueString<T>(List<T> items, string newItemValue, string comparedPropertyName)

במתודה החדשה נבצע איזשהי איטרציה (foreach / linq) ואת ההשוואה נעשה באמצעות Reflection על-מנת לקבל את הערך מאחורי ה-Property.

כמובן שכל מי שיצא לו לכתוב פתרון שכזה, היה צריך לתת את הדעת למצבים בהם המאפיין המבוקש אינו קיים, בין אם בגלל שגיאת כתיב בשם המחרוזת (דבר שניתן לרוב לגלות מהר תוך כדי הפיתוח) ובין אם בגלל באגים מתגלגלים כתוצאה מעדכון מבנה המחלקות (השמטה/שינוי של מאפיין) – באגים שיותר קשה לגלות ואשר לא פעם נגלים רק בשלב הבדיקות המאוחרות.

פתרון אחר אפשרי, למקרה שבו שמות המאפיינים ידועים בזמן הפיתוח (מתאים למקרה בו מבצעים Code Reuse כמו בדוגמה למעלה) הינו להשתמש ב-lambda expressions:

string GetUniqueString<T>(List<T> items, string newItemValue, Func<T, string> comparedProperty)

בקוד המתודה נשתמש ב-First על-מנת למצוא אם קיימים איברים כאלו ברשימה

if (items.First(i=>(comparedProperty(i) == newItemValue)) != null) ...

קריאה למתודה שכזו יכולה להראות כך:

string newFileName = GetUniqueString<File>(files, "new file", (f=>f.Name));

כך נוכל להבטיח ששם ה-Property הוא Strongly Types וכל שינוי במבנה המחלקה תגרום לשגיאת קומפילציה (בין אם שינוי שם המאפיין, מחיקתו ואפילו שינוי הטיפוס שלו).

כמובן שאפשר להרחיב מתודה זו, כך שהיא גם תדע לטפל במאפיינים שהם לאו דווקא מחרוזות ע”י הרחבת הגנריות ושימוש ב-Equals.

פתרון זה גם יכול להכתב באמצעות delegate שהרי lambdas הם מימוש של delegate, ולכן גם ניתן לתת פתרון לבעיה זו ב-2.0 net.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*