Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
.NET Framework 3.5, C# içindeki tüm temsilcilerde temsilci türleriyle eşleşen yöntem imzaları için varyans desteği sunar. Bu, temsilcilere yalnızca eşleşen imzaları olan yöntemleri değil, aynı zamanda daha fazla türetilmiş tür (kovaryans) döndüren veya temsilci türü tarafından belirtilenden daha az türetilmiş türe (ters değişken) sahip parametreleri kabul eden yöntemleri de atayabileceğiniz anlamına gelir. Buna hem genel hem de genel olmayan temsilciler dahildir.
Örneğin, iki sınıfı ve iki temsilcisi olan aşağıdaki kodu göz önünde bulundurun: genel ve genel olmayan.
public class First { }
public class Second : First { }
public delegate First SampleDelegate(Second a);
public delegate R SampleGenericDelegate<A, R>(A a);
SampleDelegate
veya SampleGenericDelegate<A, R>
türlerinin temsilcilerini oluşturduğunuzda, aşağıdaki yöntemlerden herhangi birini bu temsilcilere atayabilirsiniz.
// Matching signature.
public static First ASecondRFirst(Second second)
{ 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(); }
Aşağıdaki kod örneği, yöntem imzası ile temsilci türü arasındaki örtük dönüştürmeyi gösterir.
// 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;
Daha fazla örnek için bkz. Temsilcilerde Varyansı Kullanma (C#) ve Func ve Eylem Genel Temsilcileri için Varyansı Kullanma (C#).
Genel Tür Parametrelerinde Varyans
.NET Framework 4 veya sonraki sürümlerinde, genel tür parametreleri tarafından belirtilen farklı türlere sahip genel temsilcilerin, türlerin varyansın gerektirdiği şekilde birbirlerinden devralınması durumunda birbirlerine atanabilmesi için, temsilciler arasında örtük dönüştürmeyi etkinleştirebilirsiniz.
Gizli dönüşümü etkinleştirmek için, in
veya out
anahtar sözcüğünü kullanarak bir temsilcideki genel parametreleri kovaryant veya kontravaryant olarak açıkça bildirmeniz gerekir.
Aşağıdaki kod örneği, birlikte değişken genel tür parametresine sahip bir temsilciyi nasıl oluşturabileceğinizi gösterir.
// 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;
}
Yöntem imzalarını temsilci türleriyle eşleştirmek için yalnızca varyans desteği kullanıyorsanız ve in
anahtar sözcüğünü ve out
anahtar sözcüğünü kullanmıyorsanız, bazen özdeş lambda ifadeleri ile veya yöntemleri ile temsilcileri örnekleyebileceğinizi, ancak bir temsilciyi diğerine atayamayacağınızı fark edebilirsiniz.
Aşağıdaki kod örneğinde, SampleGenericDelegate<String>
SampleGenericDelegate<Object>
'den türetilmesine rağmen String
, açıkça Object
'e dönüştürülemez. Genel parametreyi T
anahtar sözcüğüyle out
işaretleyerek bu sorunu çözebilirsiniz.
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;
}
.NET'te Varyant Tür Parametrelerine Sahip Genel Delegeler
.NET Framework 4, var olan çeşitli genel temsilcilerde genel tür parametreleri için varyans desteği sunar:
Action
ad alanı System içinden temsilciler, örneğin Action<T> ve Action<T1,T2>Func
ad alanı System içinden temsilciler, örneğin Func<TResult> ve Func<T,TResult>Temsilci Predicate<T>
Temsilci Comparison<T>
Temsilci Converter<TInput,TOutput>
Daha fazla bilgi ve örnek için bkz. Func ve Eylem Genel Temsilcileri için Varyansı Kullanma (C#).
Genel Delegelerde Varyant Tür Parametrelerini Bildirme
Genel temsilcinin ortak değişken veya değişken karşıtı genel tür parametreleri varsa, değişken genel temsilci olarak anılabilir.
Anahtar sözcüğünü kullanarak genel bir temsilcide ortak değişken bir genel tür parametresi bildirebilirsiniz out
. Kovarant türü, yalnızca yöntem dönüş türü olarak kullanılabilir ve yöntem argümanlarının türü olarak kullanılamaz. Aşağıdaki kod örneği, kovaryant bir genel temsilcinin nasıl bildirileceğini gösterir.
public delegate R DCovariant<out R>();
Bir genel temsilcide, in
anahtar kelimesini kullanarak genel tür parametresini contravariant olarak bildirebilirsiniz. Değişken karşıtı tür, yalnızca yöntem bağımsız değişkenlerinin türü olarak kullanılabilir, yöntem dönüş türü olarak değil. Aşağıdaki kod örneği, kontrevariant jenereik bir delegenin nasıl bildirimin yapılacağını gösterir.
public delegate void DContravariant<in A>(A a);
Önemli
ref
, in
ve out
C# içindeki parametreler değişken olarak işaretlenemez.
Aynı temsilcide hem varyansı hem de kovaryansı desteklemek, ancak farklı tür parametreleri için de mümkündür. Bu, aşağıdaki örnekte gösterilmiştir.
public delegate R DVariant<in A, out R>(A a);
Değişken Genel Temsilcilerini Örnekleme ve Çağırma
Değişken temsilcilerin örneğini oluşturup çağırdığınız gibi değişken temsilcileri de başlatabilir ve çağırabilirsiniz. Aşağıdaki örnekte temsilcinin örneği bir lambda ifadesiyle oluşturulur.
DVariant<String, String> dvariant = (String str) => str + " ";
dvariant("test");
Değişken Genel Temsilcilerini Birleştirme
Değişken temsilcilerini birleştirmeyin.
Combine yöntemi değişken temsilci dönüştürmeyi desteklemez ve temsilcilerin tam olarak aynı türde olmasını bekler. Bu, Combine yöntemini veya +
işleci kullanarak temsilcileri birleştirdiğinizde, aşağıdaki kod örneğinde gösterildiği gibi, bir çalışma zamanı özel duruma yol açabilir.
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);
Değer ve Başvuru Türleri için Genel Tür Parametrelerinde Varyans
Genel tür parametreleri için varyans yalnızca başvuru türleri için desteklenir. Örneğin, tamsayı bir değer türü olduğundan DVariant<int>
örtük olarak DVariant<Object>
veya DVariant<long>
olarak dönüştürülemez.
Aşağıdaki örnek, genel tür parametrelerindeki varyansın değer türleri için desteklenmediğini gösterir.
// 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;
}