خطأ في تحويل نوع C# على الرغم من القيد العام
-
06-07-2019 - |
سؤال
لماذا، مع وجود قيد عام على معلمة النوع T من الفئة P من "يجب أن ترث من A"، تنجح المكالمة الأولى ولكن تفشل المكالمة الثانية مع خطأ تحويل النوع المفصل في التعليق:
abstract class A { }
static class S
{
public static void DoFirst(A argument) { }
public static void DoSecond(ICollection<A> argument) { }
}
static class P<T>
where T : A, new()
{
static void Do()
{
S.DoFirst(new T()); // this call is OK
S.DoSecond(new List<T>()); // this call won't compile with:
/* cannot convert from 'System.Collections.Generic.List<T>'
to 'System.Collections.Generic.ICollection<A>' */
}
}
ألا ينبغي أن يضمن القيد العام ذلك List<T>
يكون بالفعل ICollection<A>
?
المحلول
وهذا مثال على عدم C # الصورة من التغاير على الأنواع العامة (C # لا م> دعم مجموعة التغاير). C # 4 ستضيف هذه الميزة على أنواع واجهة، وكذلك سيتم تحديث عدة أنواع اجهة BCL لدعم أنها كذلك.
C # 4.0: التغاير و Contravariance :
<اقتباس فقرة>في هذا المقال سأحاول لتغطية واحدة من الابتكارات C # 4.0. واحدة من الميزات الجديدة هي التغاير و contravariance على المعلمات النوع الذي ويدعم الآن مندوبون عام واجهات عامة. اسمحوا الأول ترى ماذا تعني هذه الكلمات:)
اقتباس فقرة>نصائح أخرى
والقيد ليس له أي تأثير على المشكلة. المسألة هي ان كنت تمرير قائمة في معلمة يتطلب ICollection - C # لا يدعم التغاير لذلك تحتاج إلى يلقي صراحة قائمة إلى ICollection:
S.DoSecond((ICollection<A>) new List<T>()); // this call will be happy
لقد قمت بكتابة المعلمة DoSecond بقوة كنوع ICollection<A>.على الرغم من حقيقة أن T من النوع A، إلا أنه لا يوجد في وقت الترجمة ضمني يتم الإرسال بين القائمة<T> وIColction<A>.ستحتاج إما إلى إنشاء القائمة وإرسالها إلى ICollection<A> عند الاتصال بـ DoSecond، أو جعل DoSecond طريقة عامة بحد ذاتها.
ملحوظة:يجب دعم هذا النوع من التمثيل الضمني في الإصدار C# 4.0، والذي سيوفر تباينًا مشتركًا/تناقضًا محسّنًا كثيرًا مقارنة بما يقدمه الإصدار C# 3.0.