בחינת שונות בנציגים
השונות ב- C# מאפשרת לך להשתמש בחתימות שיטות גמישות יותר עם נציגים. הוא מאפשר לך להקצות שיטות לנציגים גם אם סוגי הפרמטרים או סוגי ההחזרה שלהם אינם זהים, כל עוד הם פועלים לפי כללים מסוימים. השונות שימושית בעת עבודה עם הירארכיות של ירושה.
מהי שונות?
השונות היא רעיון ב- C# המאפשר לך להשתמש בסוג נגזר יותר מזה שצוין בנציג או בממשק. הוא מאפשר לך ליצור קוד גמיש יותר הניתן לשימוש חוזר בכך שהוא מאפשר להקצות שיטות לנציגים גם אם החתימות שלהם אינן תואמות באופן מדויק.
קיימים שני סוגים של שונות:
- שונות משותפת: מאפשרת לפעולת שירות לכלול סוג החזרה שנגזר יותר מהסוג המוגדר בנציג.
- Contravariance: מאפשר לפעולת שירות לקבל פרמטרים הנגזרים פחות מהפרמטרים בסוג הנציג.
התמיכה השונות כוללת נציגים כלליים ולא כלליים.
שונות עם נציגים מותאמים אישית
נציגים מותאמים אישית הם סוגי נציגים המוגדרים על-ידי המשתמש. ניתן להחיל שונות על נציגים מותאמים אישית כדי להפוך אותם לגמישות יותר.
הדוגמה הבאה מדגימה כיצד להשתמש השונות עם נציגים מותאמים אישית:
public class Animal { }
public class Dog : Animal { }
// Define a delegate that takes a Dog and returns an Animal
public delegate Animal AnimalDelegate(Dog dog);
// Method that matches the delegate signature
public static Animal GetAnimal(Dog dog) => new Animal();
// Method that uses covariance (returns a more derived type)
public static Dog GetDog(Dog dog) => new Dog();
// Method that uses contravariance (accepts a less derived type)
public static Animal GetAnimalFromAnimal(Animal animal) => new Animal();
public class Program
{
public static void Main()
{
AnimalDelegate del;
// Assign method with matching signature
del = GetAnimal;
Animal animal = del(new Dog());
// Assign method with covariant return type
del = GetDog;
animal = del(new Dog());
// Assign method with contravariant parameter type
del = GetAnimalFromAnimal;
animal = del(new Dog());
}
}
בדוגמה זו, GetDog ניתן להקצות ל- AnimalDelegate מאחר Dog שהוא סוג נגזר יותר מאשר Animal (שונות משותפת). באופן דומה, GetAnimalFromAnimal ניתן להקצות מאחר שהוא Animal סוג נגזר פחות מ- Dog (contravariance).
שונות עם נציגים שהוקלידו בצורה חזקה
השונות חלה גם על נציגים שהוקלידו בצורה חזקה, כגון ו Action - Func.
שונות משותפת עם Func
הדוגמה הבאה מדגימה שונות משותפת עם Func:
public class Person { }
public class Employee : Person { }
public static Employee FindEmployee(string title) => new Employee();
public class Program
{
public static void Main()
{
// Func<string, Person> can hold a method that returns Employee
Func<string, Person> func = FindEmployee;
Person person = func("Manager");
}
}
בדוגמה זו, FindEmployee החזרת Employee, הנגזרת יותר מ- Person, ולכן ניתן להקצות אותה ל- Func<string, Person>.
Contravariance עם Action
הדוגמה הבאה מדגימה את ההפצה השונה עם Action:
public class Animal { }
public class Dog : Animal { }
public static void HandleAnimal(Animal animal) { }
public class Program
{
public static void Main()
{
// Action<Dog> can hold a method that takes Animal
Action<Dog> action = HandleAnimal;
action(new Dog());
}
}
כאן, HandleAnimal מקבל , Animalהנגזר פחות מ- Dog, ולכן ניתן להקצות אותו ל- Action<Dog>.
שונות בנוסחאות כלליות
ניתן גם להחיל את השונות על פרמטרים כלליים של סוג באמצעות מילות inout המפתח ו- .
סוג כללי של Covariant
מילת out המפתח משמשת להצהיר על פרמטר סוג כללי של covariant. תכונה זו מאפשרת לך להשתמש בסוג נגזר יותר כסוג החזרה.
הדוגמה הבאה מדגימה שונות משותפת ברכיבים כלליים:
public interface ICovariant<out T> { T Get(); }
public class Animal { }
public class Dog : Animal { }
public class CovariantExample : ICovariant<Dog>
{
public Dog Get() => new Dog();
}
public class Program
{
public static void Main()
{
ICovariant<Animal> covariant = new CovariantExample();
Animal animal = covariant.Get();
}
}
בדוגמה זו, ICovariant<out T> ניתן להקצות ICovariant<Dog> ל- מאחר ICovariant<Animal> שהוא Dog נגזר יותר מ- Animal.
סוג כללי של קונטרוואריאנט
מילת in המפתח משמשת להצהיר על פרמטר סוג כללי של contravariant. תכונה זו מאפשרת לך להשתמש בסוג נגזר פחות כסוג פרמטר.
הדוגמה הבאה מדגימה את ההפצה השונה ב- generics:
public interface IContravariant<in T> { void Set(T value); }
public class Animal { }
public class Dog : Animal { }
public class ContravariantExample : IContravariant<Animal>
{
public void Set(Animal value) { }
}
public class Program
{
public static void Main()
{
IContravariant<Dog> contravariant = new ContravariantExample();
contravariant.Set(new Dog());
}
}
כאן, IContravariant<in T> ניתן להקצות IContravariant<Animal> ל- מאחר IContravariant<Dog> שהוא Animal נגזר פחות מ- Dog.
נקודות עיקריות
- השונות מאפשרת לך להשתמש בחתימות שיטה גמישות יותר עם נציגים.
- שונות משותפת מאפשרת לפעולת שירות לכלול סוג החזרה שנגזר יותר מהסוג המוגדר בנציג.
- Contravariance מאפשר לפעולת שירות לקבל פרמטרים הנגזרים פחות מהפרמטרים בסוג הנציג.
- נציגים מותאמים אישית והקלדים חזק יכולים להשתמש השונות כדי להיות גמישים יותר.
- כלליים יכולים להשתמש שונות עם מילות המפתח ו-
inכדיoutלהצהיר על פרמטרים כלליים של קונטרוואריאנט וסוג כללי של שונות משותפת.