בהמשך לשבוע האולי טוב,
לעתים אנחנו מעוניינים לבצע איזשהו ביטוי רק במידה ואיזשהו תנאי מתקיים, למשל:
1
| ZipCode zipCode = company.Workers[0].Address.ZipCode;
|
מה הבעיה כאן? כרגיל הכל יכול להיות null, אבל בנוסף לכך ייתכן שבמערך Workers אין תוצאות.
השיטה הקלאסית לפתור בעיה כזו היא:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| ZipCode zipCode = null; if (company != null) { if ((company.Workers != null) && (company.Workers.Length > 0)) { Person worker = company.Workers[0]; if ((worker != null) && (worker.Address != null)) { zipCode = worker.Address.ZipCode; } } }
|
כמות הקוד שאנחנו מבצעים כאן רק כדי לגשת לProperty היא די מכובדת.
גם לבעיה זו יש פתרון בגישה הדומה לפתרונות של הבעיות הקודמות שראינו. ניצור Extension Method כזה:
1 2 3 4 5 6 7 8 9 10 11 12
| public static TSource If<TSource> (this TSource source, Func<TSource, bool> predicate) where TSource : class { if ((source != null) && predicate(source)) { return source; } return null; }
|
זה מחזיר לנו null אם הפרדיקט אינו מתקיים, אחרת מחזיר את האובייקט שקיבלנו לפונקציה.
כעת נוכל לכתוב את הקוד הקודם בגישה החדשה בצורה כזאת:
1 2 3 4 5
| ZipCode zipCode = company.With(x => x.Workers) .If(x => x.Length > 0) .With(x => x[0]) .With(x => x.Address) .With(x => x.ZipCode);
|
או לחלופין ככה:
1 2 3 4
| ZipCode zipCode = company.If(x => (x.Workers != null) && (x.Workers.Length > 0)) .With(x => x.Workers[0]) .With(x => x.Address) .With(x => x.ZipCode);
|
באופן דומה, נוכל ליצור Extension Method מקביל בשם Unless:
1 2 3 4 5 6 7 8 9 10 11 12
| public static TSource Unless<TSource> (this TSource source, Func<TSource, bool> predicate) where TSource : class { if ((source == null) || predicate(source)) { return null; } return source; }
|
שמחזירה את האובייקט שקיבלנו לפונקציה, רק אם הפרדיקט לא מתקיים, ואחרת null.
באמצעותה נוכל לכתוב את אותו הדבר בצורה הבאה:
1 2 3 4 5
| ZipCode zipCode = company.With(x => x.Workers) .Unless(x => x.Length == 0) .With(x => x[0]) .With(x => x.Address) .With(x => x.ZipCode);
|
המשך יום אולי טוב