2017-06-12 16 views
6

我想知道在一個功能性的方式與F#C#代碼交互的最佳方式時,當我要檢查空多次做廣泛null檢查在F#中的最佳方式。什麼是調用C#代碼

從C#,很簡單,因爲我有空操作

public bool Authorize(DashboardContext dashboardContext) 
{ 
    var context = new OwinContext(dashboardContext.GetOwinEnvironment()); 
    var user = context.Authentication.User; 
    return user?.Identity?.IsAuthenticated ?? false; 
} 

從F#,我做了這個

let authorize (ctx:DashboardContext) = 
    match OwinContext(ctx.GetOwinEnvironment()) with 
    | null -> false 
    | c -> match c.Authentication.User with 
      | null -> false 
      | user -> user.Identity.IsAuthenticated 

但我不滿意這個。做這件事的功能是什麼?我想也許一些計算表達式會有所幫助,但我不知道如何完成。

+0

您的解決方案看起來很好,這個用例。 – s952163

回答

9

Option.ofObj將可爲空的對象轉換爲Option。然後,您可以使用已在Option模塊中定義的幫助者。例如,您在那裏編寫的模式的一部分已被封裝爲Option.bind

let authorize (ctx:DashboardContext) = 
    ctx.GetOwinEnvironment() |> OwinContext |> Option.ofObj 
    |> Option.bind (fun c -> c.Authentication.User |> Option.ofObj) 
    |> Option.map (fun user -> user.Identity.IsAuthenticated) 
    |> Option.defaultValue false 

Option.bind接受一個Option<'a>而這需要類型'a並返回一個Option<'a>的功能。當它在流水線中使用時,它是「映射」Some或將其過濾爲None的一種方式。

我要說的是,你寫的函數看起來不錯其實,但這種方式可能會被認爲更地道一點點,但它無疑也有點困難,在這個榜樣。 Option.bind真正進入自己的時候,它節省了多層次的嵌套。

值得注意的是,在你的F#函數和我的這兩個函數中,我們假設AuthenticationIdentity屬性的非零值,並在訪問它們的屬性時冒空引用異常。這與使用空傳播的C#方法形成鮮明對比。目前在F#中沒有內置的方法來實現這一點,但可能有一些先進的方法來模擬它。

也可以用計算表達式來做到這一點。請參閱MaybeBuilderhere

+1

你值得擁有你的用戶名,先生**快**布朗福克斯:我剛剛開始寫我的答案,而你的答案則更加完整。 :-)我會提到,雖然,在某些情況下,簡單的'isNull'功能(這只是返回TRUE;如果輸入爲空,返回FALSE如果輸入不爲空)是有用的爲好。有時候這就是你所需要的。但在這種情況下,如果你有一連串的步驟,'Option'類型幾乎總是更好(特別是如果空值可能出現在鏈中的許多點)。 – rmunn

+4

另一個考慮:構造函數調用的結果('OwinContext')不需要進行空值檢查。構造函數調用永遠不會導致null。 –

+1

@FyodorSoikin使用類似常規函數的構造函數的缺點。很難理解這類事情。 – mydogisbox