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


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

.NET-keretrendszer 4 számos meglévő általános adapter varianciáját támogatja. 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-től kezdve a következő interfészek variánsok:

A .NET-keretrendszer 4.5-től kezdve a következő interfészek variálnak:

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. Most azonban használhatja stringsobjectsahelyett, hogy az előző példában látható módon, mert a IEnumerable<T> felület kovariant.

A contravariance lehetővé teszi, hogy egy metódus olyan argumentumtípusokat használjon, amelyek kevésbé származnak, mint a felület általános 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 most már contravariant, az osztályt öröklő BaseClass osztályok példányainak összehasonlítására használhatóBaseComparer. 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. Nem konvertálható IEnumerable<object>például IEnumerable<int> implicit módon, mert az egész számokat értéktípus jelöli.

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