C# و F# casting - على وجه التحديد "كـ" كـ "الكلمة الرئيسية"

StackOverflow https://stackoverflow.com/questions/2361851

  •  23-09-2019
  •  | 
  •  

سؤال

في 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

هل هذا صحيح؟

نعم ، هذا صحيح. (إجابتك أفضل من بقية الإجابات في رأيي.)

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