關於協變和逆變
協變和逆變統稱為變體,這是用於數組類型,委托類型,泛型參數類型間進行隱式引用轉換用的語法規則,有點類似多態。
泛型接口中的變體
<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()
{
SampleGenericDelegate dString = () => " ";
SampleGenericDelegate