DCSIMG
C# 4.0 Part 12 - Covariance and Contravariance - שלמה גולדברג (הרב דוטנט)

שלמה גולדברג (הרב דוטנט)

מרצה בסלע ויועץ בעולם ה - net.

C# 4.0 Part 12 - Covariance and Contravariance

 

המושג הזה הוא קצת וירטואלי למי שלא מכיר אותו, אז כדאי שנעבור על המושג לפני שנראה מה התחדש ב - C# 4.0.
 
 
ב - C# 2.0 יצא מושג חדש Covariance and Contravariance in Delegates 
 
Covariance אומר את הדבר הבא: אפשר להגדיר delegate שמחזיר אובייקט ולתת מתודה שבפועל מחזירה מישהו שיורש ממנו, כלומר:
 

    delegate object CovarianceDelegate();

 

    static void Main()

    {

        CovarianceDelegate cd = CovarianceMethod;

    }

 

    static Person CovarianceMethod()

    {

 

    }

 
וזה הגיוני כי זה עומד בחוקי ה - Object Oriented (שאפשר לשלוח בן לאבא).
 
 
Contravariance אומר את הדבר הבא: אפשר להגדיר delegate שמקבל אובייקט ולתת מתודה שבפועל מקבלת את האבא, כלומר:
 

    delegate void ContravarianceDelegate(Person obj);

 

    static void Main()

    {

        ContravarianceDelegate cva = ContravarianceMethod;

    }

 

    static void ContravarianceMethod(object obj)

    {

    }

 
 
וכמו שאמרתי זה היה אחד מהחידושים ב - C# 2.0, היום ב - (C# 4.0) הרחיבו את המושג Covariance and Contravariance גם עבור Generic Interface ו - Generic Delegate. (מומלץ לקרוא את ההסבר ב - MSDN).
 
למעשה Generic Interface או Generic Delegate נקראים בשם Variant אם ה - Generic Parameter (כלומר ה - T) מוגדר כ - Covariance או כ - Contravariance.
 
 
דוגמא ל - Generic Interface שה - T שלו מוגדר כ - Covariance הוא IEnumerable. הקוד הבא חוקי רק ב - C# 4.0
 

    List<string> strings = new List<string>();

    IEnumerable<object> objects = strings;

 
למעשה ה - T של IEnumerable מוגדר שהוא יכול להחזיר כל מי שיורש מ - T ולכן השורה השנייה הינה חוקית, שימו לב איך הוגדר ה - Interface.
 

   public interface IEnumerable<out T> : IEnumerable

   {

       IEnumerator<T> GetEnumerator();

   }

 
ה - out ל - T מגדיר שכל מה שיורש מ - T יכול לחזור בפונקציה GetEnumerator (וזה לא פשוט, מכיון ש - IEnumerable של string לא יורש מ - IEnumerable של object - אבל ה - out מגדיר שמסתכלים על ה - T והיות ש - string יורש מ - object אפשר לעשות את זה).
 
 
דומגא ל Interface שהוגדר כ - Contravariance הוא ICompare. הקוד הבא הינו חוקי רק ב - C# 4.0
 

    public class Class1

    {

        static void Main()

        {

            IComparer<Employee> abc = new Person();

        }

    }

    class Employee : Person

    {

    }

 

    class Person : IComparer<Person>

    {

    }

 
 
זאת אומרת שאני יכול לשלוח לאובייקט מסוג IComparer של Employee אובייקט שמממש את IComparer של Person היות ש - Person הוא האבא של Employee.
(זה הגיוני, כי אם Employee יורש מ - Person, אז ברור שמתודה שיודעת להשוות בין שני Person תדע גם להשוות בין שני Employee)
 
ה - Interface מוגדר כך:
 

    public interface IComparer<in T>

    {

        int Compare(T x, T y);

    }

 
ברגע שה - T מוגדר כ - in אפשר לשלוח פנימה כל מי ש - T יורש ממנו.
 
ב - MSDN יש כמה דוגמאות שימושיות לזה. כאן וכאן והסבר מקיף נרחב נמצא כאן
פורסם: Jul 01 2009, 09:57 AM by Shlomo | with no comments |
תגים:, , ,
שלח תגובה

(שדה חובה)  

(שדה חובה)  

(אופציונלי)

(שדה חובה) 

Please add 1 and 2 and type the answer here:


Enter the numbers above: