Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
.NET Framework 4 introducerade variansstöd för flera befintliga generiska gränssnitt. Avvikelsestöd möjliggör implicit konvertering av klasser som implementerar dessa gränssnitt.
Från och med .NET Framework 4 är följande gränssnitt variant:
IEnumerable<T> (T är covariant)
IEnumerator<T> (T är covariant)
IQueryable<T> (T är covariant)
IGrouping<TKey,TElement> (
TKeyochTElementär covariant)IComparer<T> (T är kontravariant)
IEqualityComparer<T> (T är kontravariant)
IComparable<T> (T är kontravariant)
Från och med .NET Framework 4.5 är följande gränssnitt variant:
IReadOnlyList<T> (T är covariant)
IReadOnlyCollection<T> (T är covariant)
Med kovarians kan en metod ha en mer härledd returtyp än den som definieras av den generiska typparametern i gränssnittet. För att illustrera covariance-funktionen bör du överväga dessa allmänna gränssnitt: IEnumerable<Object> och IEnumerable<String>. Gränssnittet IEnumerable<String> ärver inte gränssnittet IEnumerable<Object>. Men typen String ärver Object typen, och i vissa fall kanske du vill tilldela objekt av dessa gränssnitt till varandra. Detta visas i följande kodexempel.
IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;
I tidigare versioner av .NET Framework orsakar den här koden ett kompileringsfel i C# och, om Option Strict den är på, i Visual Basic. Men nu kan du använda strings i stället för objects, som du ser i föregående exempel, eftersom IEnumerable<T> gränssnittet är covariant.
Contravariance tillåter att en metod har argumenttyper som är mindre härledda än den som anges av den generiska parametern i gränssnittet. Anta att du har skapat en BaseComparer klass för att jämföra instanser av BaseClass klassen för att illustrera kontravarians. Klassen BaseComparer implementerar gränssnittet IEqualityComparer<BaseClass>.
IEqualityComparer<T> Eftersom gränssnittet nu är kontravariant kan du använda BaseComparer för att jämföra instanser av klasser som ärver BaseClass klassen. Detta visas i följande kodexempel.
// Simple hierarchy of classes.
class BaseClass { }
class DerivedClass : BaseClass { }
// Comparer class.
class BaseComparer : IEqualityComparer<BaseClass>
{
public int GetHashCode(BaseClass baseInstance)
{
return baseInstance.GetHashCode();
}
public bool Equals(BaseClass x, BaseClass y)
{
return x == y;
}
}
class Program
{
static void Test()
{
IEqualityComparer<BaseClass> baseComparer = new BaseComparer();
// Implicit conversion of IEqualityComparer<BaseClass> to
// IEqualityComparer<DerivedClass>.
IEqualityComparer<DerivedClass> childComparer = baseComparer;
}
}
Fler exempel finns i Använda varians i gränssnitt för generiska samlingar (C#).
Varians i allmänna gränssnitt stöds endast för referenstyper. Värdetyper stöder inte varians. Det IEnumerable<int> går till exempel inte att implicit konvertera till IEnumerable<object>, eftersom heltal representeras av en värdetyp.
IEnumerable<int> integers = new List<int>();
// The following statement generates a compiler error,
// because int is a value type.
// IEnumerable<Object> objects = integers;
Det är också viktigt att komma ihåg att klasser som implementerar variantgränssnitt fortfarande är invarianta. Även om List<T> implementerar det covarianta gränssnittet IEnumerable<T> kan du till exempel inte implicit konvertera List<String> till List<Object>. Detta illustreras i följande kodexempel.
// The following line generates a compiler error
// because classes are invariant.
// List<Object> list = new List<String>();
// You can use the interface object instead.
IEnumerable<Object> listObjects = new List<String>();