Exportieren (0) Drucken
Alle erweitern
Dieser Artikel wurde manuell übersetzt. Bewegen Sie den Mauszeiger über die Sätze im Artikel, um den Originaltext anzuzeigen. Weitere Informationen
Übersetzung
Original

Varianz in Delegaten (C# und Visual Basic)

In .NET Framework 3.5 und Visual Studio 2008 wurde die Varianzunterstützung für den Vergleich von Methodensignaturen und Delegattypen in allen Delegaten in C# und Visual Basic eingeführt. Dies bedeutet, dass Sie Delegaten nicht nur Methoden zuweisen können, die über übereinstimmende Signaturen verfügen, sondern auch Methoden, die stärker abgeleitete Typen (Kovarianz) zurückgeben oder Parameter annehmen, die weniger stark abgeleitete Typen (Kontravarianz) aufweisen, als vom Delegattyp angegeben wurde. Dies schließt sowohl generische als auch nicht generische Delegaten ein.

Betrachten Sie beispielsweise den folgenden Code, der zwei Klassen und zwei Delegaten aufweist: generisch und nicht generisch.


public class First { }
public class Second : First { }
public delegate First SampleDelegate(Second a);
public delegate R SampleGenericDelegate<A, R>(A a);


Wenn Sie Delegaten vom Typ SampleDelegate oder vom Typ SampleGenericDelegate<A, R> (SampleDelegate(Of A, R) in Visual Basic) erstellen, können Sie diesen Delegaten eine der folgenden Methoden zuweisen.


// Matching signature.
public static First ASecondRFirst(Second first)
{ return new First(); }

// The return type is more derived.
public static Second ASecondRSecond(Second second)
{ return new Second(); }

// The argument type is less derived.
public static First AFirstRFirst(First first)
{ return new First(); }

// The return type is more derived 
// and the argument type is less derived.
public static Second AFirstRSecond(First first)
{ return new Second(); }


Im folgenden Codebeispiel wird die implizite Konvertierung zwischen der Methodensignatur und dem Delegattyp veranschaulicht.


// Assigning a method with a matching signature 
// to a non-generic delegate. No conversion is necessary.
SampleDelegate dNonGeneric = ASecondRFirst;
// Assigning a method with a more derived return type 
// and less derived argument type to a non-generic delegate.
// The implicit conversion is used.
SampleDelegate dNonGenericConversion = AFirstRSecond;

// Assigning a method with a matching signature to a generic delegate.
// No conversion is necessary.
SampleGenericDelegate<Second, First> dGeneric = ASecondRFirst;
// Assigning a method with a more derived return type 
// and less derived argument type to a generic delegate.
// The implicit conversion is used.
SampleGenericDelegate<Second, First> dGenericConversion = AFirstRSecond;


Weitere Beispiele finden Sie unter Verwenden von Varianz in Delegaten (C# und Visual Basic) und unter Verwenden von Varianz für die generischen Delegaten Func und Action (C# und Visual Basic).

In .NET Framework 4 können Sie die implizite Konvertierung zwischen Delegaten aktivieren, damit generische Delegaten, für die unterschiedliche Typen von generischen Typparametern angeben werden, einander zugewiesen werden können, wenn ein Typ entsprechend den Varianzanforderungen vom jeweils anderen Typ geerbt wird.

Um die implizite Konvertierung zu aktivieren, müssen Sie generische Parameter mit dem in-Schlüsselwort oder mit dem out-Schlüsselwort in einem Delegat explizit als Kovariante oder als Kontravariante deklarieren.

Im folgenden Codebeispiel wird veranschaulicht, wie Sie einen Delegaten mit einem kovarianten generischen Typparameter erstellen können.


// Type T is declared covariant by using the out keyword.
public delegate T SampleGenericDelegate <out T>();

public static void Test()
{
    SampleGenericDelegate <String> dString = () => " ";

    // You can assign delegates to each other,
    // because the type T is declared covariant.
    SampleGenericDelegate <Object> dObject = dString;           
}


Wenn Sie Methodensignaturen und Delegattypen nur mithilfe der Varianzunterstützung vergleichen und weder das in-Schlüsselwort noch das out-Schlüsselwort verwenden, können Sie möglicherweise in einigen Fällen Delegaten mit identischen Lambda-Ausdrücken oder Methoden instanziieren, nicht jedoch die Delegaten einander zuweisen.

Im folgenden Codebeispiel kann SampleGenericDelegate<String> nicht explizit in SampleGenericDelegate<Object> konvertiert werden (SampleGenericDelegate(Of String) in SampleGenericDelegate(Of Object) in Visual Basic), obwohl String das Object erbt. Sie können dieses Problem beheben, indem Sie dem generischen Parameter T mit dem out-Schlüsselwort markieren.


public delegate T SampleGenericDelegate<T>();

public static void Test()
{
    SampleGenericDelegate<String> dString = () => " ";

    // You can assign the dObject delegate
    // to the same lambda expression as dString delegate
    // because of the variance support for 
    // matching method signatures with delegate types.
    SampleGenericDelegate<Object> dObject = () => " ";

    // The following statement generates a compiler error
    // because the generic type T is not marked as covariant.
    // SampleGenericDelegate <Object> dObject = dString;



}


Dd233060.collapse_all(de-de,VS.120).gifGenerische Delegaten mit varianten Typparametern in .NET Framework

In .NET Framework 4 wird die Varianzunterstützung für generische Typparameter in mehreren vorhandenen generischen Delegaten eingeführt:

Weitere Informationen und Beispiele finden Sie unter Verwenden von Varianz für die generischen Delegaten Func und Action (C# und Visual Basic).

Dd233060.collapse_all(de-de,VS.120).gifDeklarieren von varianten Typparametern in generischen Delegaten

Wenn ein generischer Delegat ko- oder kontravariante generische Typparameter aufweist, kann er als varianter generischer Delegat bezeichnet werden.

Mit dem out-Schlüsselwort können Sie einen generischen Typparameter in einem generischen Delegaten als Kovariante deklarieren. Der kovariante Typ kann nur als Methodenrückgabetyp verwendet werden, nicht jedoch als Methodenargumenttyp. Im folgenden Codebeispiel wird gezeigt, wie ein kovarianter generischer Delegat deklariert wird.


public delegate R DCovariant<out R>();


Mit dem in-Schlüsselwort können Sie einen generischen Typparameter in einem generischen Delegaten als Kontravariante deklarieren. Der kontravariante Typ kann nur als Methodenargumenttyp verwendet werden, nicht jedoch als Methodenrückgabetyp verwendet werden. Im folgenden Codebeispiel wird gezeigt, wie ein kontravarianter generischer Delegat deklariert wird.


public delegate void DContravariant<in A>(A a);


Wichtiger Hinweis Wichtig

ByRef -Parameter in Visual Basic sowie ref- und out-Parameter in C# können nicht als variant gekennzeichnet werden.

Varianz und Kovarianz können im gleichen Delegaten unterstützen werden, jedoch für unterschiedliche Typparameter. Dies wird im folgenden Beispiel gezeigt.


public delegate R DVariant<in A, out R>(A a);


Dd233060.collapse_all(de-de,VS.120).gifInstanziieren und Aufrufen von varianten generischen Delegaten

Variante Delegaten können analog zu nicht varianten Delegaten instanziiert und aufgerufen werden. Im folgenden Beispiel wird der Delegat durch einen Lambda-Ausdruck instanziiert.


DVariant<String, String> dvariant = (String str) => str + " ";
dvariant("test");


Dd233060.collapse_all(de-de,VS.120).gifKombinieren von varianten generischen Delegaten

Variante Delegaten sollten nicht kombiniert werden. Die Combine-Methode unterstützt nicht die Konvertierung varianter Delegaten, sondern erwartet Delegaten von genau dem gleichen Typ. Dies kann zu einer Laufzeitausnahme führen, wenn Sie mit der Combine-Methode (in C# und Visual Basic) oder mit dem Operator + (in C#) Delegaten kombinieren, wie im folgenden Codebeispiel gezeigt.


Action<object> actObj = x => Console.WriteLine("object: {0}", x);
Action<string> actStr = x => Console.WriteLine("string: {0}", x);
// All of the following statements throw exceptions at run time.
// Action<string> actCombine = actStr + actObj;
// actStr += actObj;
// Delegate.Combine(actStr, actObj);


Varianz in generischen Typparameter wird nur für Verweistypen unterstützt. Beispielsweise kann DVariant<int> (DVariant(Of Int) in Visual Basic) nicht implizit in DVariant<Object> oder DVaraint<long> (DVariant(Of Object) oder DVaraint(Of Long) in Visual Basic) konvertiert werden, da die ganze Zahl ein Werttyp ist.

Im folgenden Beispiel wird veranschaulicht, dass Varianz in generischen Typparametern für Werttypen nicht unterstützt wird.


// The type T is covariant.
public delegate T DVariant<out T>();

// The type T is invariant.
public delegate T DInvariant<T>();

public static void Test()
{
    int i = 0;
    DInvariant<int> dInt = () => i;
    DVariant<int> dVariantInt = () => i;

    // All of the following statements generate a compiler error
    // because type variance in generic parameters is not supported
    // for value types, even if generic type parameters are declared variant.
    // DInvariant<Object> dObject = dInt;
    // DInvariant<long> dLong = dInt;
    // DVariant<Object> dVariantObject = dVariantInt;
    // DVariant<long> dVariantLong = dVariantInt;            
}


Die in Visual Basic 2008 eingeführte gelockerte Delegatkonvertierung bietet eine größere Flexibilität beim Vergleich von Methodensignaturen und Delegattypen. Beispielsweise können Sie beim Zuweisen einer Methode zu einem Delegaten auf Parameterspezifikationen und Rückgabewerte verzichten. Weitere Informationen finden Sie unter Gelockerte Delegatenkonvertierung (Visual Basic).

Community-Beiträge

HINZUFÜGEN
Anzeigen:
© 2015 Microsoft