Megosztás a következőn keresztül:


Variancia az általános felületeken (C#)

A .NET-keretrendszer 4 bemutatta a variancia támogatását számos meglévő általános interfészhez. A variancia-támogatás lehetővé teszi az ezen interfészeket megvalósító osztályok implicit átalakítását.

A .NET-keretrendszer 4-es verziójától kezdve a következő interfészek változatosak:

A .NET-keretrendszer 4.5-től kezdődően a következő interfészek variáns tulajdonságokat mutatnak:

A kovariancia lehetővé teszi, hogy egy metódus származtatottabb visszatérési típussal rendelkezzen, mint amelyet az interfész általános típusparamétere határoz meg. A kovariancia funkció szemléltetéséhez vegye figyelembe az alábbi általános felületeket: IEnumerable<Object> és IEnumerable<String>. A IEnumerable<String> felület nem örökli a IEnumerable<Object> felületet. A String típus azonban örökli a Object típust, és bizonyos esetekben érdemes lehet ezeknek a felületeknek az objektumait egymáshoz rendelni. Ez az alábbi példakódban látható.

IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;

A .NET-keretrendszer korábbi verzióiban ez a kód fordítási hibát okoz A C# és ha Option Strict be van kapcsolva, a Visual Basicben. De most használhatja a strings a objects helyett, mint az előző példában, mert a IEnumerable<T> felület kovariáns.

A kontravariancia lehetővé teszi, hogy egy metódus olyan argumentumtípusokat használjon, amelyek kevésbé származnak, mint az interfész generikus paramétere által megadottak. A contravariance szemléltetéséhez tegyük fel, hogy létrehozott egy osztályt BaseComparer az BaseClass osztály példányainak összehasonlításához. Az BaseComparer osztály megvalósítja az IEqualityComparer<BaseClass> felületet. Mivel a IEqualityComparer<T> felület jelenleg kontravariáns, a BaseComparer használható olyan osztályok példányainak összehasonlítására, amelyek a BaseClass osztályt öröklik. Ez az alábbi példakódban látható.

// 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;
    }
}

További példákért lásd: Variancia használata általános gyűjteményekhez készült felületekben (C#).

Az általános felületek varianciája csak referenciatípusok esetén támogatott. Az értéktípusok nem támogatják a varianciát. Például, IEnumerable<int> nem konvertálható implicit módon IEnumerable<object>-re, mert az egész számokat értéktípus képviseli.

IEnumerable<int> integers = new List<int>();
// The following statement generates a compiler error,
// because int is a value type.
// IEnumerable<Object> objects = integers;

Azt is fontos megjegyezni, hogy a variáns interfészeket megvalósító osztályok még mindig invariánsak. Például, bár List<T> implementálja a kovariant felületet IEnumerable<T>, nem konvertálható List<String>List<Object>implicit módon. Ezt az alábbi példakód szemlélteti.

// 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>();

Lásd még