F# ما يعادل c# typeof (ienumerable <>)
-
21-09-2019 - |
سؤال
لديّ قطعة من الكود حيث أحتاج إلى معرفة ما إذا كان نوع معين ينفذ IEnumerable<T>
(لا أهتم بـ T)
لقد حاولت (t:System.Type
في حال كنت تتساءل)
let interfaces = t.GetInterfaces()
let enumerbale =
interfaces.Any(fun t ->
t.GetGenericTypeDefinition() = typeof<IEnumerable<>>
)
ومع ذلك ، لن يتم تجميع (التجميع لا يحب <>). ثم حاولت
let interfaces = t.GetInterfaces()
let enumerbale =
interfaces.Any(fun t ->
t.GetGenericTypeDefinition() = typeof<IEnumerable<'a>>
)
لكن الحصول على تحذير من أن "a هو قيد على OBJ. لا أريد معرفة ما إذا IEnumerable<obj>
يتم تنفيذه ولكن IEnumerabl<>
.
أي شخص يعرف الحل و btw لا تتردد في التعليق على الكود أعلاه أيضًا.
المحلول
هذا يجب أن يعمل:
typedefof<System.IEnumerable<_>>
تعديل
كما يلاحظ توماس ، لا يوجد شيء مميز حول _
البرية هنا ؛ و# يثير هذا النوع obj
هو النوع الأكثر قابلية للتطبيق في هذا السياق ، لذلك هذا هو نفسه استخدام typedefof<System.IEnumerable<obj>>
. في بعض الحالات ، يمكن أن تكون هذه الأعمال عائقًا قليلاً. على سبيل المثال ، إذا حددت واجهة type I<'a when 'a :> I<'a>> = interface end
, ، ثم لا يمكنك استخدام typedefof<I<_>>
, ، لان I<obj>
لا تفي بالقيود العامة ولا يمكن لـ F# استنتاج نوع آخر أكثر ملاءمة. يمكن أن يحدث هذا حتى بدون قيود متكررة (على سبيل المثال type I<'a when 'a : struct and 'a :> System.ICloneable> = interface end
. هذا على عكس نهج C#، والذي يعمل بشكل جيد تمامًا في الحالات المماثلة.
فيما يتعلق برمزك نفسه ، أعتقد أنك تريد إجراء بعض التغييرات الأخرى أيضًا ، مثل ضمان أن تكون الواجهة عامة قبل الاتصال GetGenericTypeDefinition
. إليك كيف سأكتب وظيفة الاختبار:
(fun t -> t.IsGenericType && (t.GetGenericTypeDefinition() = typedefof<_ seq>))
نصائح أخرى
على حد علمي ، فإن F# ليس لديه أي مكافئ لـ C# typeof(IEnumerable<>)
. هذا لأنه ، هذا بناء جملة خاص مدعوم بشكل صريح بواسطة C#. في F#، typeof
هي وظيفة طبيعية ويجب أن تكون وسيطة الكتابة نوعًا محددًا بالكامل. يمكنك الحصول على تعريف نوع عام برمجيًا مثل هذا:
let t = typeof<IEnumerable<obj>>
let genericT = t.GetGenericTypeDefinition()
المشكلة في الحل الخاص بك مع IEnumerable<'a>
هو أن برنامج التحويل البرمجي F# لا يزال يحتاج إلى العثور على نوع ملموس للاستخدام (لأن تعريف النوع العام ليس نوعًا صالحًا). إذا كان الاستدلال النوع يستنتج أن معلمة النوع غير مقيدة بأي شكل من الأشكال ، فإنه يستخدم النوع الافتراضي ، وهو obj
.
تعديل لم أكن أعرف عنه typedefof<IEnumerable<_>>
, هذا مفيد جدا! على أي حال ، لاحظ أن السطحي لا يحتوي على أي معنى خاص هنا - حجة النوع الفعلي لا تزال IEnumerable<obj>
, ، لكن ال typedefof
المكالمات وظيفة GetGenericTypeDefinition
خلف الكواليس.
سأكون مقصرا بعدم الإشارة إلى أن هذا السؤال هو واحد من العديد من إجاباتهم في