是否建议使用MethodBase查找用于记录目的的方法名称?

时间:2014-03-17 08:56:37

标签: c#

我的源代码中几乎每个函数都有以下代码。

string methodName = MethodBase.GetCurrentMethod().Name;

我的问题是

考虑到反射是一项代价高昂的事情,是否建议使用上述代码来实现相同目标?

这仅用于记录目的。

3 个答案:

答案 0 :(得分:8)

不,我不会在你的源代码中到处都这样做。

首先,我使用专用的日志包,它可能有巧妙的方法来做得更好,而且在源代码中肯定不那么突兀。有各种选项(log4net,nlog等)。方法名称究竟有多重要?我经常发现,如果我在邮件中记录了足够的上下文,我就不需要知道确切的方法名称。这对例外更为重要。

其次,如果您正在使用C#5,则可以使用CallerMemberNameAttribute让编译器指定为您调用日志记录功能的方法的名称。这显然比在执行时更加明智

答案 1 :(得分:1)

使用此方法获取当前方法的名称时,性能会受到重大影响,因此我不推荐使用。

人们经常提到CallerMemberNameAttribute课程,但是现在你想要使用日志记录界面通常不能很好地发挥作用。其原因是它通常作为默认参数应用,这意味着它必须转到非默认参数的右侧。许多日志API都具有以下格式:

Info(string format, params object[] values)

现在,添加具有CallerMemberNameAttribute的参数将成为一个问题。由于params参数禁止此操作,因此您无法将其置于右侧,并且您无法将其置于其他任何位置,因为它无法成为默认参数。一种选择是将您的日志记录API更改为以下内容:

Info(string format, object[] values, [CallerMemberName] string memberName = "")

但是你必须为值显式创建一个数组,这个数组往往不会流动。

答案 2 :(得分:1)

出于好奇,我决定计时GetCurrentMethod次电话。使用Stopwatch i在循环中调用GetCurrentMethod,看起来没有缓存(电话号码和时间之间的线性关系)

var sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (var i = 0; i < numberOfCallsToMake; i++)
{
    var methodName = MethodBase.GetCurrentMethod().Name;
}
sw.Stop();
Console.WriteLine("Calling GetCurrentMethod {0} times: {1} ms",numberOfCallsToMake,  sw.ElapsedMilliseconds);

给了我们

Calling GetCurrentMethod 100 times: 0 ms
Calling GetCurrentMethod 1000 times: 1 ms
Calling GetCurrentMethod 10000 times: 14 ms
Calling GetCurrentMethod 100000 times: 148 ms
Calling GetCurrentMethod 1000000 times: 1335 ms
Calling GetCurrentMethod 10000000 times: 13403 ms
Calling GetCurrentMethod 100000000 times: 134079 ms

看起来没有任何方法名称的缓存(不知道它是如何工作的)因为时间和调用次数之间存在线性关系。

日志记录框架可能更智能并存储当前方法名称以便减少这些毫秒数,您也可以从中获得额外的好处。因此,请遵循Jon Skeet的建议并使用日志框架