Wednesday, April 18, 2012

Hello, this is C# method. Who is Calling me?

And there was no easier answer other than going through the stack trace and scanning the frames yourself. Well this is just made easier in Visual Studio 2011 Beta and we will be discussing the same feature today. This provides a method details about the caller.

Why should I care?
It seems that you haven't been involved in chasing and tracing some weird flow in which your code is executed. This has always been a pain for most of us. Sometimes, the only option left is to write a bunch of Trace.WriteLine() with some text to identify the method. Then at the end of usecase, you look at the trace to find out exactly what was the flow of execution of your code. This feature is provided to further support this tracing, debugging and diagnostics.

What Information does it provide?
This is an optional details that you can add to all or some of your methods. With the new features, you can get the following information easily:
  1. The compile time path of the source file of the caller.
  2. Line Number in the source file where the method is called
  3. The name of member [Property or Method] of the caller.
How is this feature supported in the framework?
This feature is supported by providing new attributes in System.Runtime.CompilerServices namespace in mscorlib.


How can I use them in my C# code?
These attributes are targeted for methods. We need to decorate the parameters with any of these attributes and the run-time would populate them with the relevant information as promised. This is built on top of another great C# feature. It is called optional parameters. This would have all the limitations of optional parameter i.e. these parameters must be the last parameters of the methods and they should have some default values assigned based on their types. CallerMemberNameAttribute and CallerFilePathAttribute may be assigned a string value. CallerLineNumberAttribute must be specified with some integer value.


Let's create a C# console application and update Program.cs as follows:


Here we have used all three of the newly available attributes in CallerInfoMethod definition. We are calling the method from within the same class from Main method. Let's run the application and see what it prints on the console.


Can I use more than One Attribute for a Parmeter?
I don't know why you would do that but you might be a bigger creative thinker than me. You might want to combine the information from those attributes. So to answer that, Yes you can use CallerFilePathAttribute and CallerMemberNameAttribute with the same parameter. They cannot be used with CallerLineNumberAttribute because of different data types. But the information is not combined instead, as I have noticed, CallerFilePathAttribute takes precedence and overrides CallerMemberNameAttribute. Let's update the same method as follows:


When we run the above code, we notice this override behavior:


Possible Improvement
I have seen most of the developers shooting down any and all ideas which involve System.Runtime.CompilerServices, and there is a reason for that. This is based on Microsoft's recommendation:

The classes in System.Runtime.CompilerServices are for compiler writers' use only.

I don't buy to this and clearly we use other things from the namespace too, like when unit testing InternalsVisibleTo is used very often. I think that it would be better if these new attributes are moved to System.Diagnostics instead. This should keep everyone happy.

Microsoft Zindabad!!!

No comments: