I just came across the C# 5 Caller Info Attributes (http://msdn.microsoft.com/en-us/library/hh534540.aspx).
This seems like a very useful feature, and I've read up some documentation (http://www.codeproject.com/Tips/606379/Caller-Info-Attributes-in-Csharp).
However, I'm just wondering: Why does one have to pass in default values? How are they used?
The following example code shows how one would use the Caller Info Attributes:
public static void ShowCallerInfo([CallerMemberName]
string callerName = null, [CallerFilePath] string
callerFilePath = null, [CallerLineNumber] int callerLine=-1)
{
Console.WriteLine("Caller Name: {0}", callerName);
Console.WriteLine("Caller FilePath: {0}", callerFilePath);
Console.WriteLine("Caller Line number: {0}", callerLine);
}
My question is: What are the default values of null
, null
, and -1
used for? How is the code above different from:
public static void ShowCallerInfo([CallerMemberName]
string callerName = "hello", [CallerFilePath] string
callerFilePath = "world", [CallerLineNumber] int callerLine=-42)
{
Console.WriteLine("Caller Name: {0}", callerName);
Console.WriteLine("Caller FilePath: {0}", callerFilePath);
Console.WriteLine("Caller Line number: {0}", callerLine);
}
The way I understand it, these are optional parameters, and the compiler supplies the default value, replacing whatever default value we assign. In that case, why are we specifying the default values? Is there some weird edge case where the compiler may not be able to fill in the values, and resorts to the defaults we had supplied? If not, then why are we being asked to enter this data? It seems rather clumsy to ask devs to supply defaults which won't ever be used.
Disclaimer: I tried googling this but I wasn't able to find anything. I'm almost afraid of asking questions on SO because most such newbie questions are met with such hostility, but as a last resort I'm going to hazard a question. Moderators/senior users, no offense intended - I really did try and find information elsewhere before posting this.
There are a few uses mentioned in other answers which all seem valid.
Something they have missed was that these essentially tells the compiler to rewrite the calls to these functions with static values. But these values are not always available. In those cases, the compiler will not rewrite the calls, so the default values will be used.
Examples:
If you compile a dll with a function that has these attributes, expose that to an in memory generated script, (say via Roslyn), that code may not have a "filename".
csc mycodefile.cs
) wont work with dynamic compilation at runtime even with the same context which would be confusing.You can also invoke this method via reflection, which the compiler simply isnt aware of to add these values.
You can also add [CallerMemberName]
to an attribute constructor and apply that attribute on a class. This will not have a member name.
See Member Names in Docs
Attribute constructor
The name of the method or property to which the attribute is applied. If the attribute is any element within a member (such as a parameter, a return value, or a generic type parameter), this result is the name of the member that's associated with that element.
No containing member (for example, assembly-level or attributes that are applied to types)
The default value of the optional parameter.
You can also provide the values explicitly, if you want to hide the caller information. for some reason. (May be if you use code obfuscation, these values may not affected, so you may want to provide these values in those cases to hide the caller).
See Remarks in Docs
Caller Info values are emitted as literals into the Intermediate Language (IL) at compile time. Unlike the results of the StackTrace property for exceptions, the results aren't affected by obfuscation.
You can explicitly supply the optional arguments to control the caller information or to hide caller information.