Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Caller Info Attributes in C# 5.0

0.00/5 (No votes)
13 Jun 2013 1  
Caller Info attributes in C# 5.0 and their usage

Introduction

I was going through the features of C#5.0 and one thing that I found interesting was CallerInfoAttributes. These attributes help in tracking information about the caller (method,property etc.) There are three types of attributes which are useful in doing so. 

  • [CallerMemberName] - Sets the information about caller member name. 
  • [CallerFilePath] - Sets the information about caller's source code file. 
  • [CallerLineNumber] - Sets the information about caller's line number.

Overall these attributes act as debugger information on call stack. Only catch here is that this is applicable for default parameters, in which case these attributes inform compiler to extract caller information and set it inside the default values of these parameters.  

Using the code 

Let's see the code for doing this. 

using System;
using System.Runtime.CompilerServices;
public class CallerInfoDemo
{
    public static void Main()
    {
        ShowCallerInfo();
        Console.ReadKey();
    }
    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);
    }
}

Output: Considering the fact that our program runs from path h:\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1\Class1.cs output is as follows. 

Caller Name: Main
Caller FilePath: h:\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1\Class1.cs
Caller Line number: 7 

These three attributes can be useful when you may want to trace all the calls to specific function. 

Another use of [CallerMemberName] is in simplifying INotifyPropertyChanged. This attribute is useful in logging the caller name as well as events notification which involve single property change. 

This is useful in WPF in viewmodel of MVVM(Model-View-ViewModel) pattern. In WPF we use INotifyPropertyChanged interface to notify UI about the changes in viewmodel. INotifyPropertyChanged has following structure.

public interface INotifyPropertyChanged
{
    event PropertyChangedEventHandler PropertyChanged;
}

public delegate void PropertyChangedEventHandler (object sender, PropertyChangedEventArgs e);

public class PropertyChangedEventArgs : EventArgs
{
    public PropertyChangedEventArgs (string propertyName);
    public virtual string PropertyName { get; }
}

Note that whenever property is changed, one need to pass the property name to the PropertyChangedEventHandler method of class implementing INotifyPropertyChanged. Consider the following code. 

public class EmployeeVM:INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged("Name");
        }
    }

    private string _phone;

    public string Phone
    {
        get { return _phone; }
        set
        {
            _phone = value;
            OnPropertyChanged("Phone");
        }
    }    
}

As you can see that in all the properties we need to hardcode the strings or may be you can define them in constants. Still we are at risk when property name is changed and if this notification call is not modified then change is the property will not be updated in UI.

To avoid all this we can make use of [CallerMemberName] attribute with propertyName as default parameter. Now new OnPropertyChanged method looks like below shown. 

public class EmployeeVM:INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged([CallerMemberName] string propertyName=null)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            // The compiler converts the above line to:
            // RaisePropertyChanged ("Name");
        }
    }

    private string _phone;

    public string Phone
    {
        get { return _phone; }
        set
        {
            _phone = value;
            OnPropertyChanged();
	    // The compiler converts the above line to:
            // RaisePropertyChanged ("Phone");
        }
    }
} 

Points of Interest 

This helps in avoiding unnecessary hard-coding or number of constants for just sake of property name. Of course when you need to update/refresh more than one property in the setter of some property then you need to pass that property's name explicitly, but as long as you want to update only one property then this attribute is very useful. I hope you will find this information helpful if not amazing. 

Thanks.  

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here