關於協變和逆變
協變和逆變統稱為變體,這是用於數組類型,委托類型,泛型參數類型間進行隱式引用轉換用的語法規則,有點類似多態。
泛型接口中的變體
<1>協變
接口中聲明的方法的泛型返回類型,它可以接受派程度更大的返回類型
interface ICovariant{ R GetSomething(); // The following statement generates a compiler error. // void SetSometing(R sampleArg); }
interface IContravariant{ void SetSomething(A sampleArg); void DoSomething () where T : A; // The following statement generates a compiler error. // A GetSomething(); }
<3> 協變和抗變的同時實現
interface IVariant{ R GetSomething(); void SetSomething(A sampleArg); R GetSetSometings(A sampleArg); }
namespace ConsoleApplication24 { // Simple hierarchy of classes. public class Person { public string FirstName { get; set; } public string LastName { get; set; } } public class Employee : Person { } // The custom comparer for the Person type // with standard implementations of Equals() // and GetHashCode() methods. class PersonComparer : IEqualityComparer{ public bool Equals(Person x, Person y) { if (Object.ReferenceEquals(x, y)) return true; if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) return false; return x.FirstName == y.FirstName && x.LastName == y.LastName; } public int GetHashCode(Person person) { if (Object.ReferenceEquals(person, null)) return 0; int hashFirstName = person.FirstName == null ? 0 : person.FirstName.GetHashCode(); int hashLastName = person.LastName.GetHashCode(); return hashFirstName ^ hashLastName; } } class Program { public static void Test() { List employees = new List { new Employee() {FirstName = "Michael", LastName = "Alexander"}, new Employee() {FirstName = "Jeff", LastName = "Price"} }; // You can pass PersonComparer, // which implements IEqualityComparer , // although the method expects IEqualityComparer . IEnumerable noduplicates = employees.Distinct (new PersonComparer()); foreach (var employee in noduplicates) Console.WriteLine(employee.FirstName + " " + employee.LastName); } public static void Main() { Test(); } } }
public delegate T SampleGenericDelegate(); public static void Test() { SampleGenericDelegate dString = () => " "; // You can assign delegates to each other, // because the type T is declared covariant. SampleGenericDelegate
public static void Test() { SampleGenericDelegatedString = () => " "; SampleGenericDelegate