سؤال

لديّ قطعة من الكود حيث أحتاج إلى معرفة ما إذا كان نوع معين ينفذ 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 خلف الكواليس.

سأكون مقصرا بعدم الإشارة إلى أن هذا السؤال هو واحد من العديد من إجاباتهم في

كيف يبدو رمز C# هذا في F#؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top