我的源代码中几乎每个函数都有以下代码。
string methodName = MethodBase.GetCurrentMethod().Name;
我的问题是
考虑到反射是一项代价高昂的事情,是否建议使用上述代码来实现相同目标?
这仅用于记录目的。
答案 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的建议并使用日志框架