簡體   English   中英

F# 4.5.0.0:錯誤 FS0193:此表達式是 function 值,即缺少 arguments。 它的類型是 Exception -> 'a

[英]F# 4.5.0.0: error FS0193: This expression is a function value, i.e. is missing arguments. Its type is Exception -> 'a

我正在將 class 從 C# 調整為 F#,在代碼中我有一個引發異常的方法,並且此方法需要具有通用返回。 When in C# to F# it works perfectly, but from F# to F# a compilation error happens: FS0193 This expression is a function value, ie is missing arguments. 它的類型是 Exception -> 'a.

        member this.Throw() =
            try
               raise ...
            with
            | exc -> ...
            Unchecked.defaultof<'T> // <- Error

如果需要完整類型,我會編輯問題。

好的,格斯。 編輯:我的目標是將 FSharp.Core 版本 4.5.0.0 移植到 .NET 4.0。 為了實現我的目標,我在 F# 中重寫了 Theraot.Core 的部分內容,因為 FSharp.Core 不“接受”第三方庫: https://github.com/theraot/Theraot/issues/121

C# 中的 Class: https://github.com/theraot/Theraot/blob/master/Framework.Core/System/Runtime/ExceptionServices/ExceptionDispatchInfo

輸入 F#:

namespace System.Runtime.ExceptionServices

open System
open Microsoft.FSharp.Core
open System.Text
open System.Reflection

/// <summary>
///     The ExceptionDispatchInfo object stores the stack trace information and Watson information that the exception
///     contains at the point where it is captured. The exception can be thrown at another time and possibly on another
///     thread by calling the ExceptionDispatchInfo.Throw method. The exception is thrown as if it had flowed from the
///     point where it was captured to the point where the Throw method is called.
/// </summary>
[<Sealed;AllowNullLiteral>]
type ExceptionDispatchInfo private(exc : exn) =

    let _stackTrace = exc.StackTrace
    static member val private _remoteStackTraceString : FieldInfo = null with get, set

    /// <summary>
    ///     Gets the exception that is represented by the current instance.
    /// </summary>
    member val SourceException = exc with get

    /// <summary>
    ///     Creates an ExceptionDispatchInfo object that represents the specified exception at the current point in code.
    /// </summary>
    /// <param name="source">The exception whose state is captured, and which is represented by the returned object.</param>
    /// <returns>An object that represents the specified exception at the current point in code. </returns>
    static member Capture(source : exn) =
        if source = null
            then raise(new ArgumentNullException "source")
        new ExceptionDispatchInfo(source)

    /// <summary>
    ///     Throws the exception that is represented by the current ExceptionDispatchInfo object, after restoring the state
    ///     that was saved when the exception was captured.
    /// </summary>
    member this.Throw() =
        try
            raise this.SourceException
        with
        | exc ->
            let newStackTrace = _stackTrace + ExceptionDispatchInfo.BuildStackTrace(Environment.StackTrace)
            ExceptionDispatchInfo.SetStackTrace(this.SourceException, newStackTrace)
            raise

    static member private BuildStackTrace(trace : string) =
        let items = trace.Split([|Environment.NewLine|], StringSplitOptions.RemoveEmptyEntries)
        let newStackTrace = new StringBuilder()
        let mutable found = false
        let mutable contains = false
        for item in items do
            if not contains then
                if item.Contains ":" then
                    if item.Contains "System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()"
                        then contains <- true
                    else
                        if found
                            then newStackTrace.Append Environment.NewLine |> ignore
                        found <- true
                        newStackTrace.Append item |> ignore
                elif found
                    then contains <- true
        newStackTrace.ToString()

    static member private GetFieldInfo() =
        if ExceptionDispatchInfo._remoteStackTraceString = null then
            // ---
            // Code by Miguel de Icaza
            let mutable remoteStackTraceString = typeof<Exception>.GetField("_remoteStackTraceString", BindingFlags.Instance ||| BindingFlags.NonPublic)
            if remoteStackTraceString = null then remoteStackTraceString <- typeof<Exception>.GetField("remote_stack_trace", BindingFlags.Instance ||| BindingFlags.NonPublic)
            ExceptionDispatchInfo._remoteStackTraceString <- remoteStackTraceString
        ExceptionDispatchInfo._remoteStackTraceString

    static member private SetStackTrace(exc : exn, value) =
        let remoteStackTraceString = ExceptionDispatchInfo.GetFieldInfo()
        remoteStackTraceString.SetValue(exc, value)

發生錯誤的地方: https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/async.fs#L65

如果 Gus 需要更多信息或截圖,請發表評論。

問題是你翻譯的C# throw; 就像raise - 但這是不正確的。 如果要重新拋出當前異常,需要使用reraise reraise() function:

member this.Throw() =
    try
        raise this.SourceException
    with
    | exc ->
        let newStackTrace = _stackTrace + 
            ExceptionDispatchInfo.BuildStackTrace(Environment.StackTrace)
        ExceptionDispatchInfo.SetStackTrace(this.SourceException, newStackTrace)
        reraise()

在您的原始代碼中發生的情況是Throw()方法不返回值,而是返回raise function 的值,這是一個引發給定異常的 function。 這在語法上是有效的,但類型與您預期的不同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM