29. Generic constraints

בהמשך לשבוע הגנרי הטוב,

נניח שיש לנו פונקציה פשוטה שמוצאת מקסימום של מערך נתון:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static int Max(int[] array)
{
if (array.Length == 0)
{
throw new ArgumentException("Array was empty",
"array");
}
else
{
int currentMax = array[0];
foreach (int element in array)
{
if (currentMax < element)
{
currentMax = element;
}
}
return currentMax;
}
}

כרגיל לשבוע, אין שום דבר מיוחד בint, והיינו רוצים שהפונקציה תעבוד גם לchar, ulong, long וכו’.

אלא שכשננסה להפוך את הפונקציה לגנרית נקבל את השגיאה הבאה בקימפול:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static T Max<T>(T[] array)
{
if (array.Length == 0)
{
throw new ArgumentException("Array was empty",
"array");
}
else
{
T currentMax = array[0];
foreach (T element in array)
{
if (currentMax < element)
{
currentMax = element;
}
}
return currentMax;
}
}

Operator ‘ ‘T’ does not contain a definition for ‘CompareTo’ and no extension method ‘CompareTo’ accepting a first argument of type ‘T’ could be found (are you missing a using directive or an assembly reference?)

כדי לפתור בעיות מסוג וכאלה, המציאו עוד כלי מאוד חזק לעבודה עם Generics – Generic constraints.

הפונקציה CompareTo אכן קיימת, אבל בממשק IComparable (או IComparable<T>).

היינו רוצים בעצם שרק T שמממש את IComparable יוכל להיכנס לפונקציה הזאת.

נוכל לעשות זאת כך:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static T Max<T>(T[] array)
where T : IComparable
{
if (array.Length == 0)
{
throw new ArgumentException("Array was empty",
"array");
}
else
{
T currentMax = array[0];
foreach (T element in array)
{
if (element.CompareTo(currentMax) > 0)
{
currentMax = element;
}
}
return currentMax;
}
}

הwhere מציין שהפונקציה יכולה לקבל רק T שמקיים את התנאים הכתובים אחריו.

נוכל לכתוב שם בין השאר איזה ממשקים אנחנו רוצים שT יממש, ומאיזה מחלקה אנחנו רוצים שהוא ירש.

על המחלקה שאנחנו רוצים שהוא ירש ממנה יש מספר הגבלות: היא לא יכולה להיות System.Array (תכתבו פשוט T[] בארגומנטים), System.Delegate, System.Enum, System.ValueType או object.

נראה הרבה מאוד דברים מגניבים שאפשר לעשות עם זה בטיפים הבאים.

יום גנרי מעולה

שתף