此处标注了属性和C#示例,但FSharp看起来不可能.
// using System.Runtime.CompilerServices
// using System.Diagnostics;
public void DoProcessing()
{
TraceMessage("Something happened.");
}
public void TraceMessage(string message,
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0)
{
Trace.WriteLine("message: " + message);
Trace.WriteLine("member name: " + memberName);
Trace.WriteLine("source file path: " + sourceFilePath);
Trace.WriteLine("source line number: " + sourceLineNumber);
}
Run Code Online (Sandbox Code Playgroud)
样本输出:
message: Something happened.
member name: DoProcessing
source file path: c:\Users\username\Documents\Visual Studio 2012\Projects\CallerInfoCS\CallerInfoCS\Form1.cs
source line number: 31
Run Code Online (Sandbox Code Playgroud)
是否可以在F#中执行上述操作,如果是,那么符号是什么?
Tom*_*cek 10
快速搜索编译器源代码显示该名称CallerMemberName不会出现在代码中的任何位置,因此我认为不支持此功能.(您当然可以使用属性标记参数,但这些属性是特殊的 - 它们指示编译器,而不是在运行时以某种方式被发现和使用.)
更新2016年7月:截至6月底,F#现在支持 CallerLineNumber和CallerFilePath,但CallerMemberName仍是不存在的.不幸的是,似乎特别难以实现这一点.
在相关的说明中,F#有一些特殊的标识符,可以让您获取当前的源文件名和行号,因此您可以使用__SOURCE_DIRECTORY__ 和__LINE__
(但不是来自C#中的调用者)获取类似的信息.
这是一个快速的 'n' 脏 hack,它滥用inline获取此信息:
module Tracing =
open System
open System.Text.RegularExpressions
let (|TraceInfo|_|) (s:string) =
let m = Regex.Match(s, "at (?<mem>.+?) in (?<file>.+?\.[a-zA-Z]+):line (?<line>\d+)")
if m.Success then
Some(m.Groups.["mem"].Value, m.Groups.["file"].Value, int m.Groups.["line"].Value)
else None
let inline trace s =
printfn "%s" s
match Environment.StackTrace with
| TraceInfo(m, f, l) ->
printfn " Member: %s" m
printfn " File : %s" f
printfn " Line : %d" l
| _ -> ()
Run Code Online (Sandbox Code Playgroud)
它实际上或多或少确实有效:
