In .NET, you can just do "new StackTrace()" to capture the current stack of the calling thread. One minor risk with this may be if an optimiser has elided function calls (e.g. converted to a tail recursion). I'm not sure how realistic this is in the C#/.NET case, but having the information injected by the compiler eliminates the possibility.
Also, .NET stack traces only contain line numbers if the debugging symbols are deployed. With the attributes, the C# compiler can inject line numbers at compile time, obviating the need for symbols. Similarly, if a vendor uses an obfuscator, the stack trace will include obfuscated names but the compiler attributes will have injected the real names, making it much easier for developers to read the log files.
Finally, for scenarios like INotifyPropertyChanged, having the caller name injected at compile time is much more efficient at run-time than capturing an entire stack trace just to figure out which property setter is running. This may not a big consideration for logging, but for property setters it is definitely worth bearing in mind.
Also, .NET stack traces only contain line numbers if the debugging symbols are deployed. With the attributes, the C# compiler can inject line numbers at compile time, obviating the need for symbols. Similarly, if a vendor uses an obfuscator, the stack trace will include obfuscated names but the compiler attributes will have injected the real names, making it much easier for developers to read the log files.
Finally, for scenarios like INotifyPropertyChanged, having the caller name injected at compile time is much more efficient at run-time than capturing an entire stack trace just to figure out which property setter is running. This may not a big consideration for logging, but for property setters it is definitely worth bearing in mind.