C# و F# casting - على وجه التحديد "كـ" كـ "الكلمة الرئيسية"
سؤال
في C# يمكنني فعل:
var castValue = inputValue as Type1
في F#، يمكنني القيام:
let staticValue = inputValue :> Type1
let dynamicValue = inputValue :?> Type1
لكن أيا منهما لا يعادل الكلمة الرئيسية لـ C# as
.
أعتقد أنني بحاجة إلى إجراء تعبير مطابق للمادة المكافئة في F#
match inputValue with
| :? Type1 as type1Value -> type1Value
| _ -> null
هل هذا صحيح؟
المحلول
على حد علمي ، لا يحتوي F# على أي مشغل مدمج يعادل C# as
لذلك تحتاج إلى كتابة بعض التعبير أكثر تعقيدًا. بدلاً من ذلك باستخدام التعليمات البرمجية الخاصة بك match
, ، يمكنك أيضا استخدام if
, ، لأن المشغل :?
يمكن استخدامها بنفس طريقة is
في C#:
let res = if (inputValue :? Type1) then inputValue :?> Type1 else null
يمكنك بالطبع كتابة وظيفة لتغليف هذا السلوك (عن طريق كتابة وظيفة عامة بسيطة تأخذ Object
ويلقيها بمعلمة النوع العام المحدد):
let castAs<'T when 'T : null> (o:obj) =
match o with
| :? 'T as res -> res
| _ -> null
يعود هذا التنفيذ null
, ، لذلك يتطلب أن يكون المعلمة النوع null
كقيمة مناسبة (بدلاً من ذلك ، يمكنك استخدامها Unchecked.defaultof<'T>
, ، وهو ما يعادل default(T)
في C#). الآن يمكنك الكتابة فقط:
let res = castAs<Type1>(inputValue)
نصائح أخرى
أود استخدام نمط نشط. هذا هو الشخص الذي أستخدمه:
let (|As|_|) (p:'T) : 'U option =
let p = p :> obj
if p :? 'U then Some (p :?> 'U) else None
هنا هو استخدام عينة من As
:
let handleType x =
match x with
| As (x:int) -> printfn "is integer: %d" x
| As (s:string) -> printfn "is string: %s" s
| _ -> printfn "Is neither integer nor string"
// test 'handleType'
handleType 1
handleType "tahir"
handleType 2.
let stringAsObj = "tahir" :> obj
handleType stringAsObj
يمكنك إنشاء المشغل الخاص بك للقيام بذلك. هذا متطابق تقريبًا مع مثال توماس ، ولكنه يظهر طريقة مختلفة قليلاً للاتصال بها. هذا مثال:
let (~~) (x:obj) =
match x with
| :? 't as t -> t //'
| _ -> null
let o1 = "test"
let o2 = 2
let s1 = (~~o1 : string) // s1 = "test"
let s2 = (~~o2 : string) // s2 = null
أعتقد أنني بحاجة إلى إجراء تعبير مطابق للمادة المكافئة في F#
match inputValue with | :? Type1 as type1Value -> type1Value | _ -> null
هل هذا صحيح؟
نعم ، هذا صحيح. (إجابتك أفضل من بقية الإجابات في رأيي.)