我遇到了问题和解决方案。我不明白为什么解决方案有效。
以下是一些使用消息#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(µsoftLoginEnabled, 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(µsoftLoginEnabled, 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 µsoftLoginEnabled 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
参数。