Exploring Caller Info Attributes

Last year, Microsoft announced a simple new feature in C# 5: Caller Info Attributes.  These attributes let you to create methods with optional parameters and tell the compiler to pass the caller’s filepath, line number, or member name instead of the parameter’s default value.  This allows you to create logging methods that automatically know where they’re being called.

When the feature was announced, I wrote a couple of blog posts that delved into some of the corner cases of the new feature.  At the time, there was no public implementation, so they were pure conjecture.

This morning, Microsoft released the beta of Visual Studio 11, which is the first public build supporting these attributes.  Now, I can finally test my theories.  Here are the results:

Although these classes are new to the .Net Framework 4.5, you can still use this feature against older framework versions by creating your own classes in the System.Runtime.CompilerServices namespace.  However, the feature will only work if the code calling the method is compiled with the C# 5 compiler; older compilers will ignore the attributes and simply pass the parameters’ default values.

All of the attributes can only be applied to arguments of types that have standard (not custom) implicit conversions to int or string.  This means that it isn’t practical to overflow [CallerLineNumber] (the compiler ran out of memory first), so I can’t test how that behaves.

Using [CallerMemberName] on field initializers passes the field name, and on static or instances constructors passes the string ".cctor" or ".ctor" (as documented)  In indexers, it passes "Item".

If a class has a constructor that takes only caller info attribute parameters, and you create another class that inherits it and does not declare a constructor (thus implicitly passing optional parameters), it passes the line number and file name of the class keyword in the derived class, but leaves the declared default for the member name (I suspect that’s a bug). 

If you do declare a constructor, it passes the string ".ctor" as the member name for the implicit base() call (just like a normal method call from inside a constructor) and the line number of the beginning of the constructor declaration.  If you actually write a base() call, it passes the line number of the base keyword.

If a call spans multiple lines, [CallerLineNumber] passes the line containing the openning parenthesis.

Delegates are fully supported; if you call a delegate that has an argumented annotated with a caller info attribute, the compiler will insert the correct value, regardless of the method you’re actually calling (which the compiler doesn’t even know).

LINQ query comprehension syntax is not supported at all; if you create a (for example) Select() method that contains a caller info attribute, then call it from a LINQ query (not lambda syntax), the compiler will crash (!).  (they will fix that)

Expression trees do not support optional parameters at all, so that corner case is irrelevant.

Attributes are the most interesting story.  What should happen if you declare a custom attribute that takes parameters with caller info attributes, then apply that attribute in various cases?  This could potentially be very useful, since there is currently no way for an attribute to know what it’s being applied to. (I hadn’t thought of this usage when I wrote the original blog post)

The documentation says that this will work in all cases, and that [CallerMemberName] will pass whatever the attribute is being applied to.  However, in the beta build, this doesn’t always work.

Attributes applied to method arguments or return values do not pass any caller info at all.  Attributes applied to types or generic type arguments do not pass member names (this is very disappointing)

Hopefully, those will be fixed before release.

15 comments:

This comment has been removed by the author.

This blog article is nice and I like it, thank you :)

This blog article is nice, thank you for informastion...

Thanks for sharing such informative guide on .Net technology. This post gives me detailed information about the .net technology. I am working as trainer in leading IT training academy offering Dot Net Training in Chennai and i use your guide to educate my students. .Net Training in Chennai

This blog article is very good, I like it !!!

Thanks really valuable. Will certainly share site with my good friends.
hotmail login

Wow, wonderful blog layout! How long have you been blogging for? you make blogging look easy. The overall look of your website is excellent, as well as the content!.
88sears

I enjoyed over read your blog post. Your blog have nice information, I got good ideas from this amazing blog. I am always searching like this type blog post. I hope I will see again.
* Street view

kami dari Murni Jaya Printing menyediakan Cetak Spanduk Murah di Jakarta Timur jadi hubungi kami jika anda butuh Cetak Spanduk 24 Jam di Jakarta Timur

nice and I like it, thank you
Wait for next article

Your site has a lot of useful information for myself. I visit regularly. Hope to have more quality items
stickman

Jasa Jilid Hard Cover Murah 24 Jam Jakarta Pusat Salemba
Jasa Jilid Hard Cover Murah 24 Jam Jakarta Pusat
Jasa Jilid Murah Jakarta Pusat, Salemba
Jasa Jilid Soft Cover Murah 24 jam Jakarta Pusat Salemba
Jasa Jilid Soft Cover Murah 24 jam Jakarta Pusat

Thanks for sharing informative article. Download Windows 7 ultimate for free from getintopc. It helps you to explore full functionality of windows operating system.

Post a Comment