Free Trial

Safari Books Online is a digital library providing on-demand subscription access to thousands of learning resources.


  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • DownloadDownload
  • PrintPrint
Share this Page URL
Help

4. Advanced C# > Caller Info Attributes (C# 5)

Caller Info Attributes (C# 5)

From C# 5, you can tag optional parameters with one of three caller info attributes, which instruct the compiler to feed information obtained from the caller’s source code into the parameter’s default value:

  • [CallerMemberName] applies the caller’s member name

  • [CallerFilePath] applies the path to caller’s source code file

  • [CallerLineNumber] applies the line number in caller’s source code file

The Foo method in the following program demonstrates all three:

using System;
using System.Runtime.CompilerServices;

class Program
{
  static void Main()
  {
    Foo();
  }

  static void Foo (
    [CallerMemberName] string memberName = null,
    [CallerFilePath] string filePath = null,
    [CallerLineNumber] int lineNumber = 0)
  {
    Console.WriteLine (memberName);
    Console.WriteLine (filePath);
    Console.WriteLine (lineNumber);
  }
}

Assuming our program resides in c:\source\test\Program.cs, the output would be:

Main
c:\source\test\Program.cs
8

As with standard optional parameters, the substitution is done at the calling site. Hence, our Main method is syntactic sugar for this:

static void Main()
{
  Foo ("Main", @"c:\source\test\Program.cs", 8);
}

Caller info attributes are useful for logging—and for implementing patterns such as firing a single change notification event whenever any property on an object changes. In fact, there’s a standard interface in the .NET Framework for this called INotifyPropertyChanged (in System.ComponentModel):

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; }
}

Notice that PropertyChangedEventArgs requires the name of the property that changed. By applying the [CallerMemberName] attribute, however, we can implement this interface and invoke the event without ever specifying property names:

public class Foo : INotifyPropertyChanged
{
  public event PropertyChanged = delegate { }

  void RaisePropertyChanged ([CallerMemberName] string propertyName = null)
  {
    PropertyChanged (this, new PropertyChangedEventArgs (propertyName));
  }

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