F#编译器:类型实例化涉及byref类型

时间:2016-09-07 21:32:25

标签: f# byref

我遇到了问题和解决方案。我不明白为什么解决方案有效。

以下是一些使用消息#34打破F#编译器的代码;类型实例化涉及byref类型":

let updateExternalLoginProperty(isEnabled: bool byref, value: bool, name: string) =
    let anyExternalLoginEnabledBeforePropertyIsSet = this.AnyExternalLoginEnabled
    this.RaiseAndSetIfChanged(&isEnabled, value, name) |> ignore
    if (this.AnyExternalLoginEnabled <> anyExternalLoginEnabledBeforePropertyIsSet) then this.RaisePropertyChanged("AnyExternalLoginEnabled")

member this.FacebookLoginEnabled with get() = facebookLoginEnabled  and set(value) = updateExternalLoginProperty(&facebookLoginEnabled, value, "FacebookLoginEnabled")
member this.GoogleLoginEnabled with get() = googleLoginEnabled and set(value) = updateExternalLoginProperty(&googleLoginEnabled, value, "GoogleLoginEnabled") |> ignore
member this.MicrosoftLoginEnabled with get() = microsoftLoginEnabled and set(value) = updateExternalLoginProperty(&microsoftLoginEnabled, value, "MicrosoftLoginEnabled") |> ignore
member this.TwitterLoginEnabled with get() = twitterLoginEnabled and set(value) = updateExternalLoginProperty(&twitterLoginEnabled, value, "TwitterLoginEnabled") |> ignore
member this.AzureActiveDirectoryLoginEnabled with get() = azureActiveDirectoryLoginEnabled and set(value) = updateExternalLoginProperty(&azureActiveDirectoryLoginEnabled, value, "AzureActiveDirectoryLoginEnabled") |> ignore
member this.AnyExternalLoginEnabled with get() = this.FacebookLoginEnabled || this.GoogleLoginEnabled || this.MicrosoftLoginEnabled || this.TwitterLoginEnabled || this.AzureActiveDirectoryLoginEnabled

updateExternalLoginProperty的调用下突出显示编译器错误。

为了使编译器错误消失,我只需将let绑定更改为私有成员变量:

member private this.UpdateExternalLoginProperty(isEnabled: bool byref, value: bool, name: string) =
    let anyExternalLoginEnabledBeforePropertyIsSet = this.AnyExternalLoginEnabled
    this.RaiseAndSetIfChanged(&isEnabled, value, name) |> ignore
    if (this.AnyExternalLoginEnabled <> anyExternalLoginEnabledBeforePropertyIsSet) then this.RaisePropertyChanged("AnyExternalLoginEnabled")

member this.FacebookLoginEnabled with get() = facebookLoginEnabled  and set(value) = this.UpdateExternalLoginProperty(&facebookLoginEnabled, value, "FacebookLoginEnabled")
member this.GoogleLoginEnabled with get() = googleLoginEnabled and set(value) = this.UpdateExternalLoginProperty(&googleLoginEnabled, value, "GoogleLoginEnabled") |> ignore
member this.MicrosoftLoginEnabled with get() = microsoftLoginEnabled and set(value) = this.UpdateExternalLoginProperty(&microsoftLoginEnabled, value, "MicrosoftLoginEnabled") |> ignore
member this.TwitterLoginEnabled with get() = twitterLoginEnabled and set(value) = this.UpdateExternalLoginProperty(&twitterLoginEnabled, value, "TwitterLoginEnabled") |> ignore
member this.AzureActiveDirectoryLoginEnabled with get() = azureActiveDirectoryLoginEnabled and set(value) = this.UpdateExternalLoginProperty(&azureActiveDirectoryLoginEnabled, value, "AzureActiveDirectoryLoginEnabled") |> ignore
member this.AnyExternalLoginEnabled with get() = this.FacebookLoginEnabled || this.GoogleLoginEnabled || this.MicrosoftLoginEnabled || this.TwitterLoginEnabled || this.AzureActiveDirectoryLoginEnabled

这可以完成它应该做的所有事情(即,只有在有外部登录可用时,UI才会显示分隔符)。我不明白为什么这个改变应该修复编译。

类型实例化是编译器引用updateExternalLoginProperty函数的创建吗?为什么要把它变成一个成员变量来规避这种非法类型的实例化呢?

作为一个侧面问题,nameof什么时候进入F#?这些神奇的弦乐让我很伤心。

更新

基于ildjam的回答(你不能在元组中有一个byref),我回到let绑定,只有三个参数而不是一个:

let updateExternalLoginProperty (isEnabled: bool byref) (value: bool) (name: string) =
    let anyExternalLoginEnabledBeforePropertyIsSet = this.AnyExternalLoginEnabled
    this.RaiseAndSetIfChanged(&isEnabled, value, name) |> ignore
    if (this.AnyExternalLoginEnabled <> anyExternalLoginEnabledBeforePropertyIsSet) then this.RaisePropertyChanged("AnyExternalLoginEnabled")

member this.FacebookLoginEnabled with get() = facebookLoginEnabled  and set(value) = updateExternalLoginProperty &facebookLoginEnabled value "FacebookLoginEnabled"
member this.GoogleLoginEnabled with get() = googleLoginEnabled and set(value) = updateExternalLoginProperty &googleLoginEnabled value "GoogleLoginEnabled"
member this.MicrosoftLoginEnabled with get() = microsoftLoginEnabled and set(value) = updateExternalLoginProperty &microsoftLoginEnabled value "MicrosoftLoginEnabled"
member this.TwitterLoginEnabled with get() = twitterLoginEnabled and set(value) = updateExternalLoginProperty &twitterLoginEnabled value "TwitterLoginEnabled"
member this.AzureActiveDirectoryLoginEnabled with get() = azureActiveDirectoryLoginEnabled and set(value) = updateExternalLoginProperty &azureActiveDirectoryLoginEnabled value "AzureActiveDirectoryLoginEnabled"
member this.AnyExternalLoginEnabled with get() = this.FacebookLoginEnabled || this.GoogleLoginEnabled || this.MicrosoftLoginEnabled || this.TwitterLoginEnabled || this.AzureActiveDirectoryLoginEnabled

这也有效。这是一个有趣的区别:成员变量有三个参数;原始let绑定只有一个tuple参数。

0 个答案:

没有答案