Caller info attributes are one of the new features of C# 5. They’re attributes applied to optional method parameters that enable you to pass caller information implicitly to a method. I’m not sure that description is very clear, so an example will help you understand:
static void Log(
string message,
[CallerMemberName] string memberName = null,
[CallerFilePath] string filePath = null,
[CallerLineNumber] int lineNumber = 0)
{
Console.WriteLine(
"[{0:g} - {1} - {2} - line {3}] {4}",
DateTime.UtcNow,
memberName,
filePath,
lineNumber,
message);
}
The method above takes several parameters intended to pass information about the caller: calling member name, source file path and line number. The Caller* attributes make the compiler pass the appropriate values automatically, so you don’t have to specify the values for these parameters:
static void Foo()
{
Log("Hello world");
// Equivalent to:
// Log("Hello world", "Foo", @"C:\x\y\z\Program.cs", 18);
}
This is of course especially useful for logging methods…
Notice that the Caller* attributes are defined in the .NET Framework 4.5. Now, suppose we use Visual Studio 2012 to target an earlier framework version (e.g. 4.0): the caller info attributes don’t exist in 4.0, so we can’t use them… But wait! What if we could trick the compiler into thinking the attributes exist? Let’s define our own attributes, taking care to put them in the namespace where the compiler expects them:
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
public class CallerMemberNameAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
public class CallerFilePathAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
public class CallerLineNumberAttribute : Attribute
{
}
}
If we compile and run the program, we can see that our custom attributes are taken into account by the compiler. So they don’t have to be defined in mscorlib.dll like the “real” ones, they just have to be in the right namespace, and the compiler accepts them. This enables us to use this cool feature when targeting .NET 4.0, 3.5 or even 2.0!
Note that a similar trick enabled the creation of extension methods when targeting .NET 2.0 with the C# 3 compiler: you just had to create an ExtensionAttribute class in the System.Runtime.CompilerServices namespace, and the compiler would pick it up. This is also what enabled LinqBridge to work.





Tried this in .NET 4.0 Visual Studio 2010 on Windows 7 and it didn”t work. Do I need to think about anything more than copy pasting your namespace code into one of my files and using the attributes? Do I need a special version of the compiler?
Hi Akku, you need C# 5 for this to work; VS 2010 uses the C# 4 compiler, so it can”t work. This trick is only useful for VS2012 projects that target .NET 4.
Ah, okay, thanks a lot for this clarification.
For someone reading this and wondering, you can of course use regular reflection e.g. using new System.Reflection.StackFrame(1).GetMethod() in C# 4.0.
Yes, but be careful with the stack technique: if the method is inlined, it won”t show up in the stack, so it StackFrame.GetMethod will return the caller.
Great work!
I tried it in VS2012 targeting framework 4.0 but all I get is empty file path,line as well as member Name.
Do I missing something?
Do you tried it Frank coz its not working here mate.
Yes, I tried it, and it works fine. I don”t usually post something on my blog without testing it first
Are you sure you declared the attributes in the correct namespace?
@Manish: I had the same problem, won”t fix for me, used the workaround posted above.