مشاركة عبر


الفرق في المفوضون (C# و Visual Basic)

‏‫NET Framework 3.5. و ‏‫Visual Studio 2008. يقدمان الدعم لمطابقة تواقيع الأسلوب مع أنواع المفوض في كل التفويضات في C# و Visual Basic . هذا يعني أنه يمكنك تعيين ليس فقط الأساليب التي تحتوي على تواقيع مطابقة ,بل الأساليب التي ترجع على أنواع أكثر اشتقاقاً (التباين المشترك) أو التي تقبل المعلمات التي تحتوي على أنواع أقل اشتقاق (contravariance) من تلك المحددة بواسطة نوع المفوض ليس فقط. يتضمن هذا كلاالتفويضات العامة و غير العامة.

على سبيل المثال، يجب مراعاة التعليمات البرمجية التالية ، والتي يتضمن فئتين و تفويضين: عام و غير عام.

Public Class First
End Class

Public Class Second
    Inherits First
End Class

Public Delegate Function SampleDelegate(ByVal a As Second) As First
Public Delegate Function SampleGenericDelegate(Of A, R)(ByVal a As A) As R
public class First { }
public class Second : First { }
public delegate First SampleDelegate(Second a);
public delegate R SampleGenericDelegate<A, R>(A a);

عندما تقوم بإنشاء التفويضات SampleDelegateأو أنواعSampleGenericDelegate<A, R>( SampleDelegate(Of A, R)في Visual Basic) يمكنك تعيين أحد الأساليب التالية إلى المفوضين.

' Matching signature.
Public Shared Function ASecondRFirst(
    ByVal second As Second) As First
    Return New First()
End Function

' The return type is more derived.
Public Shared Function ASecondRSecond(
    ByVal second As Second) As Second
    Return New Second()
End Function

' The argument type is less derived.
Public Shared Function AFirstRFirst(
    ByVal first As First) As First
    Return New First()
End Function

' The return type is more derived 
' and the argument type is less derived.
Public Shared Function AFirstRSecond(
    ByVal first As First) As Second
    Return New Second()
End Function
// 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(); }

مثال التعليمات البرمجية توضح التحويل الضمني بين توقيع الأسلوب و نوع التفويض.

' Assigning a method with a matching signature 
' to a non-generic delegate. No conversion is necessary.
Dim dNonGeneric As SampleDelegate = AddressOf 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.
Dim dNonGenericConversion As SampleDelegate = AddressOf AFirstRSecond

' Assigning a method with a matching signature to a generic delegate.
' No conversion is necessary.
Dim dGeneric As SampleGenericDelegate(Of Second, First) = AddressOf ASecondRFirst
' Assigning a method with a more derived return type 
' and less derived argument type to a generic delegate.
' The implicit conversion is used.
Dim dGenericConversion As SampleGenericDelegate(Of Second, First) = AddressOf AFirstRSecond
// 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;

لمزيد من المعلومات، راجع استخدام الفرق في المفوضون (C# و Visual Basic) و استخدام الفرق Func و إجراء التفويضات العام (C# و Visual Basic) .

الالفرق في معلمات النوع العام

في ".NET Framework 4،" يمكنك تمكين التحويل الضمني بين التفويضات, بحيث delegates عام أن يكون لديك أنواع مختلفة المحدد بواسطة النوع العام معلمات يمكن تعيينها إلى بعضها البعض إذا الأنواع موروثة من بعضها البعض كما هو مطلوب بواسطة الالفرق.

لتمكين التحويل الضمني يجب أن تصرح معلمات عامة في تفويض في طردي أو contravariant بإستخدام inأو الكلمة الأساسية out.

يوضح مثال التعليمة البرمجية التالية كيف يمكنك إنشاء تفويض الذي يحتوي على نوع معلمة عام طردي.

' Type T is declared covariant by using the out keyword.
Public Delegate Function SampleGenericDelegate(Of Out T)() As T
Sub Test()
    Dim dString As SampleGenericDelegate(Of String) = Function() " "
    ' You can assign delegates to each other,
    ' because the type T is declared covariant.
    Dim dObject As SampleGenericDelegate(Of Object) = dString
End Sub
// 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;           
}

في حالة إستخدام دعم الالفرق فقط لمطابقة التواقيع أسلوب مع تفويض أنواع و لا تستخدم inو outوالكلمات الأساسية قد تجد في بعض الأحيان يمكن إنشاء مثيل التفويضات مع تعبيرات لامدا متطابقة أو أساليب ولكن لا يمكنك تعيين مفوض واحد إلى آخر.

في المثال التعليمات البرمجية التالية, SampleGenericDelegate<String>لا يمكن أن تكون محولة بوضوح إلى SampleGenericDelegate<Object>( SampleGenericDelegate(Of String)إلى SampleGenericDelegate(Of Object)في Visual Basic) ، على الرغم من أن Stringيرث Object. إصلاح هذه المشكلة عن طريق وضع علامة معلمة عامة Tمع الكلمة الأساسيةout.

Public Delegate Function SampleGenericDelegate(Of T)() As T
Sub Test()
    Dim dString As SampleGenericDelegate(Of String) = Function() " "

    ' 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.
    Dim dObject As SampleGenericDelegate(Of Object) = Function() " "

    ' The following statement generates a compiler error
    ' because the generic type T is not marked as covariant.
    ' Dim dObject As SampleGenericDelegate(Of Object) = dString


End Sub
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;



}

المفوضين العامين ممن لديهم نوع معلمات Variant في .NET Framework

4 .NET Framework يقدم دعمًا الالفرق معلمات نوع عام في عدة التفويضات العامة الموجودة:

لمزيد من المعلومات والأمثلة ، انظراستخدام الفرق Func و إجراء التفويضات العام (C# و Visual Basic) .

تصريح معلمات نوع المتغير في التفويضات العامة

إذا كان التفويض العام يحتوي طردي أو contravariant النوع العام معلمات، يمكن الإشارة إلى أنه متغير تفويض عام .

إمكانية تعريف نوع المعلمة عام طردي في تفويض عام بإستخدام الكلمة الأساسية out. يمكن إستخدام نوع طردي فقط بنوع إرجاع أسلوب و لا بنوع وسيطات الأسلوب. يظهر مثال التعليمات البرمجية التالية كيفية التصريح بتفويض عام طردي.

Public Delegate Function DCovariant(Of Out R)() As R
public delegate R DCovariant<out R>();

إمكانية تعريف نوع المعلمة عام طردي في تفويض عام بإستخدام الكلمة الأساسية in. يمكن إستخدام النوع الضد البديل فقط كنوع وسيطات أسلوب و لا بنوع إرجاع الأسلوب. يظهر مثال التعليمات البرمجية التالية كيفية التصريح بتفويض عام ضد بديل.

Public Delegate Sub DContravariant(Of In A)(ByVal a As A)
public delegate void DContravariant<in A>(A a);

هام

المعلماتByRef في Visual Basic وrefوoutالمعلمات في C# و لا يمكن وضعها كعلامة متغير.

من الممكن أيضاً دعم كل من التباين و التباين المشترك في نفس تفويض, ولكن لمعلمات أنوع مختلفة. كما هو موضح في المثال التالي:

Public Delegate Function DVariant(Of In A, Out R)(ByVal a As A) As R
public delegate R DVariant<in A, out R>(A a);

إنشاء و استدعاء مفوضون متغير عام

يمكنك إنشاء مثيل ثم استدعاء التفويضات المتغيرة تماماً كما تقوم بإنشاء مثيل استدعاء التفويضات الثابتة. في المثال التالي تفويض إنشاء مثيل بالتعبير lambda.

Dim dvariant As DVariant(Of String, String) = Function(str) str + " "
dvariant("test")
DVariant<String, String> dvariant = (String str) => str + " ";
dvariant("test");

الالفرق في عام معلمات نوع القيمة وأنوع المرجع

يتم اعتماد الالفرق معلمة نوع عام من أجل أنواع المرجع. على سبيل المثال، DVariant<int>( DVariant(Of Int)في Visual Basic) لا يمكن تحويله ضمنيًا إلى DVariant<Object>أو DVaraint<long>( DVariant(Of Object)أو DVaraint(Of Long)في Visual Basic) ، لأن العدد الصحيح هو نوع القيمة.

يوضح المثال التالي ذلك الالفرق في نوع عام لا يتم اعتماد معلمات لأنواع القيمة.

' The type T is covariant.
Public Delegate Function DVariant(Of Out T)() As T
' The type T is invariant.
Public Delegate Function DInvariant(Of T)() As T
Sub Test()
    Dim i As Integer = 0
    Dim dInt As DInvariant(Of Integer) = Function() i
    Dim dVaraintInt As DVariant(Of Integer) = Function() 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.
    ' Dim dObject As DInvariant(Of Object) = dInt
    ' Dim dLong As DInvariant(Of Long) = dInt
    ' Dim dVaraintObject As DInvariant(Of Object) = dInt
    ' Dim dVaraintLong As DInvariant(Of Long) = dInt
End Sub
// 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;            
}

حالة تفويض تحويل في Visual Basic

حالة التفويضconversion المقدمة في ‏‫Visual Basic 2008, تمكن مرونة أكثر في مطابقة توقيعات الأسلوب مع أنواع التفويض. على سبيل المثال، فإنه يسمح لك بحذف مواصفات المعلمة و حذف دالة قيم الإرجاع عندما تقوم بتعيين أسلوب إلى لمفوض. لمزيد من المعلومات، راجع تحويل حالة تفويض.

راجع أيضًا:

المرجع

استخدام الفرق Func و إجراء التفويضات العام (C# و Visual Basic)

موارد أخرى

generics في .NET Framework