A number of years ago .NET added a small feature called Caller Member Info. This isn’t the biggest feature out there, and you’re not going to use this frequently unless you’re doing a lot of XAML development, but it’s good to have in your tool belt.
Caller Member Info attributes allow you to simplify your code by providing more information to individual methods without having to pass in explicit values.
In this short article I’ll give you an overview of the caller member info attributes, how they work, and the problems they can solve.
Let’s say you have code that does some standard checks:
There’s some obvious code duplication here. We can clean it up by extracting a method:
Okay, cool. We now have logic in one method, but having to pass in the method name is a little irritating.
This is where
CallerMemberNameAttribute comes into play. Let’s take a look at an improved version of the code and then discuss how it works:
Note here that the code is barely changed. We added
[CallerMemberName] to the
methodName parameter on
CheckInput and also made
methodName optional by giving it a default value of an empty string.
The optional parameter allows the code to compile, and then .NET inspects the
CallerMemberName attribute at runtime and injects IL code to switch from the default value to that of the name of the method that just called the executing method.
For example, in
CheckInput is called and the
methodName parameter is not specified. Instead of taking the default value of
CallerMemberName attribute sets the value of
DoBar, the caller.
Admittedly it’s an interesting parlor trick for developer parties (I don’t know for sure, I don’t get invites to those), but how is this actually useful?
For one, logging methods can frequently benefit from knowing who called them.
For another, if you do work with model view view model frameworks (MVVM) such as XAML that rely on things like
INotifyPropertyChanged, you frequently need to state the name of the property that changed. This allows our code to be very simple:
We also copy and paste code more than we’d like to admit – even small pieces of code. Why? Because we hate boilerplate and logging, validation, and property changed notifications are all boiler-plate things.
If we copy and paste and forget to change the name, mistype it, or we rename a method or property down the road without changing the string value, these all can lead to bugs and confusion. Admittedly, the
nameof keyword can help with the renaming scenario, but the point remains: Code you don’t have to write won’t break.
This is a point I’m quite fond of making, but it’s true. If you don’t have to code something, you won’t make a mistake doing it.
Okay, so we talked at length at how
CallerMemberName gets us the name of the method or property that invoked the method.
Beyond that, we also have the CallerLineNumberAttribute and CallerFilePathAttribute. Both work similarly to
CallerLineNumber works with an integer) and will provide orienting information on the source code as it existed at compile time.
Realistically you won’t use these nearly as much as
CallerMemberName. The only reason I’ve needed either of these two attributes has been around error logging code.
If you’d like to read more, check out Microsoft’s documentation on Caller Member Info.
If you do use any of these attributes for something I haven’t mentioned, I’d love to hear about it. Please send me a note in the comments or on twitter.