כפי שציינתי הרבה פעמים בעבר, אחד מהמבנים שאני מוצא את עצמי משתמש בהם הרבה מאוד הוא משהו כזה:
1
| Dictionary<string, ICollection<int>>
|
זהו Dictionary שהValues שלו הם Collection, למשל PKים של אנשים שהשם שלהם הוא מסוים וכו’.
הבעיה היא שממש לא נוח להוסיף לו ערכים, נצטרך לכתוב קוד כזה:
1 2 3 4 5 6 7 8 9 10 11 12
| IDictionary<string, ICollection<int>> namesToPks = new Dictionary<string, ICollection<int>>(); ICollection<int> requestedNamesPks; if (!namesToPks.TryGetValue(givenName, out requestedNamesPks)) { requestedNamesPks = new List<int>(); namesToPks.Add(givenName, requestedNamesPks); } requestedNamesPks.Add(givenPk);
|
במקום זאת אפשר לעשות את מה שאני מדבר עליו כבר שבוע וחצי.
ניצור Extension Method כזה:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public static void Add<TKey, TValue, TValueCollection> (this IDictionary<TKey, TValueCollection> dictionary, TKey key, TValue value) where TValueCollection : ICollection<TValue>, new() { TValueCollection requestedValue; bool wasValueFound = dictionary.TryGetValue(key, out requestedValue); if (!wasValueFound) { requestedValue = new TValueCollection(); dictionary.Add(key, requestedValue); } requestedValue.Add(value); }
|
עכשיו נוכל לכתוב קוד כזה בכיף ובניחותא:
1 2 3 4
| IDictionary<string, List<int>> namesToPks = new Dictionary<string, List<int>>(); namesToPks.Add(givenName, givenPk);
|
שימו לב שהקומפיילר מגלה Implicitly מהם הפרמטרים הגנריים!
יותר יפה, לא?
הבעיה היחידה כאן היא שאנחנו חייבים של TValueCollection יהיה Constructor ולכן לא יכול להיות ICollection<TValue>.
במקום זאת נוכל לעשות Extension Method טיפה יותר גנרי:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public static void Add<TKey, TValue, TValueCollection, TCollection> (this IDictionary<TKey, TValueCollection> dictionary, TKey key, TValue value) where TValueCollection : ICollection<TValue> where TCollection : TValueCollection, new() { TValueCollection requestedValue; bool wasValueFound = dictionary.TryGetValue(key, out requestedValue); if (!wasValueFound) { requestedValue = new TCollection(); dictionary.Add(key, requestedValue); } requestedValue.Add(value); }
|
וליצור שני overloadים:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public static void Add<TKey, TValue, TValueCollection> (this IDictionary<TKey, TValueCollection> dictionary, TKey key, TValue value) where TValueCollection : ICollection<TValue>, new() { dictionary.Add <TKey, TValue, TValueCollection, TValueCollection> (key, value); } public static void Add<TKey, TValue> (this IDictionary<TKey, ICollection<TValue>> dictionary, TKey key, TValue value) { dictionary.Add <TKey, TValue, ICollection<TValue>, List<TValue>> (key, value); }
|
וכעת נוכל לקרוא בשתי הדרכים:
1 2 3 4
| IDictionary<string, ICollection<int>> namesToPks = new Dictionary<string, ICollection<int>>(); namesToPks.Add(givenName, givenPk);
|
וגם בדרך הזו:
1 2 3 4
| IDictionary<string, List<int>> namesToPks = new Dictionary<string, List<int>>(); namesToPks.Add(givenName, givenPk);
|
שיהיה אחלה יום מורחב