C# 获取当前类和方法名称是否会降低性能?

C# 获取当前类和方法名称是否会降低性能?,c#,C#,我有一个日志类,它创建了一个log4net实例,我可以在代码中的任何地方调用它。我还有一个方法来找出调用方的类和方法名。以下是我的方法: private static string CurrentMethod() { StackTrace stackTrace = new StackTrace(); MethodBase method = stackTrace.GetFrame(2).GetMethod(); string cn = method.ReflectedTyp

我有一个日志类,它创建了一个log4net实例,我可以在代码中的任何地方调用它。我还有一个方法来找出调用方的类和方法名。以下是我的方法:

private static string CurrentMethod()
{
    StackTrace stackTrace = new StackTrace();
    MethodBase method = stackTrace.GetFrame(2).GetMethod();
    string cn = method.ReflectedType.Name;
    string mn = method.Name;

    string output = "[" + cn + "." + mn + "]";
    return output;
}
我发现了这些文章:,,以及其他许多文章,但没有一篇讨论效率和性能。 现在我有两个问题: 1-我可以在一个大项目中使用这种方法吗?一秒钟内大约1000个请求?我的意思是,这对项目的效率和绩效有多大影响? 2-Os有更好的方法来编写上述方法吗

这里也是我的日志类的一部分。我想这会有帮助:

public static class Tools_Log
{
    private static ILog logger;

    public static ILog GetLogger()
    {
        return logger ?? (logger = CreateLogger());
    }
    private static ILog CreateLogger()
    {
        //Some log4net initialization
        return LogManager.GetLogger("WebService");
    }

    private static string CurrentMethod()
    {
        StackTrace stackTrace = new StackTrace();
        MethodBase method = stackTrace.GetFrame(2).GetMethod();
        string cn = method.ReflectedType.Name;
        string mn = method.Name;

        string output = "[" + cn + "." + mn + "]";
        return output;
    }

    public static string MessageForLogFile(string message, string exeption, double time)
    {
        string currentMethod;
        string executiontime;
        string consumer;
        string body;
        string output;

        currentMethod = CurrentMethod();
        executiontime = ExecutionTime(time);
        body = BodyForLog(message, exeption);
        consumer = Consumer();

        output = OutPut(currentMethod, executiontime, consumer, body);
        return output;
    }
}
我这样调用log类:

Tools_Log.GetLogger().Info(Tools_Log.MessageForLogFile("some text", "some text", execution time));
public void UserMethod()
{
    IntermediaryMethod();
}

public void IntermediaryMethod([CallerMemberName] caller = "")
{
    LogMethod(caller)
}

public void LogMethod([CallerMemberName] caller = "")
{
    // Log...
}

谢谢。

是的,反射总是一个较慢的过程。如果您想知道方法的名称,可以使用。添加一个默认值为空的字符串参数,并对其应用该属性,编译器将为您发送名称

此外,如果您正在寻找快速日志记录,请查看ETW而不是Log4Net

在这里:

在这里:

编辑: 至于你在评论中的问题,不幸的是,你不能把方法2的名称提高,至少不能直接提高。CallerMemberName基本上只是语法糖,它告诉编译器获取调用成员的名称,并将其放置在参数中,因此它在单个级别上工作。但是,由于它依赖于默认参数来执行此操作,因此如果手动发送参数,则CallerMemberName功能不适用,因此可以执行以下操作:

Tools_Log.GetLogger().Info(Tools_Log.MessageForLogFile("some text", "some text", execution time));
public void UserMethod()
{
    IntermediaryMethod();
}

public void IntermediaryMethod([CallerMemberName] caller = "")
{
    LogMethod(caller)
}

public void LogMethod([CallerMemberName] caller = "")
{
    // Log...
}

如果您自己传递一个值,它将不会被覆盖,因此这样做将允许您从两个级别获得调用方的名称,同时保留单个级别的功能。

必须测量性能,这是使用探查器完成的

顺便说一句,您可以使用.NET4.5中引入的属性,而不是使用StackTrace类


虽然[CallerMemberName]属性不提供类名,但[CallerFilePath]提供了定义调用方成员的源代码文件的完整路径,这对于调试/记录来说可能更好,因为您知道在何处调查可能的错误或错误。

如回答中所述,新的CallerMemberNameAttribute是一个救命稻草。如果由于某种原因,您一直使用较旧的.net framework版本,那么获取特定的stackframe应该比获取整个stacktrace具有更好的性能,尤其是对于较大的堆栈,例如新的StackFrame2,false.GetMethod;您可能还需要考虑编译器可以优化/内联一些方法调用,以及您所看到的堆栈跟踪,或者CaleReMeNeNess名称可能与调试时所看到的不匹配。注意,在C 6中,可以使用NAMEOF表达式,例如静态空隙MyMetry{String N=NAMEOFMY方法;/*.*/}。如果以后重命名MyMethod,这是安全的,因为在编译时会检查标识符MyMethod是否存在,拼写是否正确等等。亲爱的@CKII,谢谢。但是你怎么知道打电话的人的名字呢?我的意思是我使用stackTrace.GetFrame2.GetMethod;查找调用方名称,因为它在我的日志类中。谢谢。@Dan将参数添加到MessageForLogFile方法中。然后,您将获得调用该方法的任何人的姓名,这就是您要查找的人。谢谢。但有时我需要再回去一次。用stackTrace很容易。我可以用CallerMemberNameAttribute完成吗?需要注意的是,[CallerFilePath]在编译时提供类的完整文件路径:这是编译时的文件路径。因此,如果您将代码移动到另一台电脑,它将始终具有相同的路径,如果该路径是您的桌面,则您的电脑用户名将显示在Windows用户的路径中。