I'm adapting a class from C# to F#, in the code I have a method that throws an exception and this method needs to have a generic return. 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. Its type is Exception -> 'a.
member this.Throw() =
try
raise ...
with
| exc -> ...
Unchecked.defaultof<'T> // <- Error
If the complete type is needed, I edit the question.
Ok Gus. Edit: My goal is to port FSharp.Core version 4.5.0.0 to .NET 4.0. To achieve my goal I am rewriting parts of Theraot.Core in F#, since FSharp.Core does not "accept" third party libraries: https://github.com/theraot/Theraot/issues/121 .
Type in 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)
Where the error occurs: https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/async.fs#L65
If Gus needs more information or screenshots, just comment.
The problem is that you translated C# throw;
as just raise
- but this is not correct. If you want to re-throw the current exception, you need to use the reraise()
function:
member this.Throw() =
try
raise this.SourceException
with
| exc ->
let newStackTrace = _stackTrace +
ExceptionDispatchInfo.BuildStackTrace(Environment.StackTrace)
ExceptionDispatchInfo.SetStackTrace(this.SourceException, newStackTrace)
reraise()
What happens in your orginal code is that the Throw()
method does not return a value, but instead returns the value of the raise
function, which is a function that throws a given exception. This is syntactically valid, but has a differnt type than you expect.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.