X

Using nameof operator in C#

There’s one very useful and often overlooked operator in C#. It’s called nameof and its purpose is to return name of something. Although it is operator we can live without it may still commit to coding by pointing out some errors at compile time. Here’s how to use the nameof operator in practice.

How nameof operator works?

Nameof operator can return names of different code artifacts. Here is simple console program that demonstrates different uses of nameof operator.

namespace NameofDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(nameof(NameofDemo));
            Console.WriteLine(nameof(Program));
            Console.WriteLine(nameof(Program.Main));
            Console.WriteLine(nameof(Main));
            Console.WriteLine(nameof(args));
        }
    }
}

This program gives the following output.

NameOfDemo
Program
Main
Main
args

As we can see it returns name of whatever code item we specifiy.

What’s the point of nameof operator? If we change name of some code item then we have to update all nameof operators applied to it because otherwise build fails. We can use nameof operator to make compiler point out some bugs that otherwise may be found when program is in production.

Behind the compiler

I will use dotPeek by JetBrains to see what compiler produced. What we see in Visual Studio and what was actually produced by compiler are not always same things. Here’s the Main() method shown above.

Even those who don’t know .NET Intermediate Language (IL) should understand what happened – there’s no nameof operator on .NET runtime level. Compiler replaces nameof operator calls with name of code item it was applied on and names are stored as strings in compiled code. It’s all static, not dynamic. Don’t even try to do something smart.

Using nameof operator to check arguments

Let’s start with something simple to use in whatever project where we write C# code. Often we need to check argument values to make sure they are valid. As code is in constant change then we can use nameof operator with method or constructor arguments to make sure we are using correct names in argument exceptions.

public class Person
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }

    public Person(string firstName, string lastName)
    {
        if(string.IsNullOrEmpty(firstName))
        {
            throw new ArgumentException("First name is required", nameof(firstName));
        }

        if (string.IsNullOrEmpty(lastName))
        {
            throw new ArgumentException("Last name is required", nameof(lastName));
        }
    }
}

Although this example is about constructor we can use nameof operator same way with method arguments.

Using nameof operator with INotifyPropertyChanged in MVVM

MVVM view models use INotifyPropertyChanged interface or some base class that implements it. When some property of view model changes then NotifyPropertyChanged event is fired so WPF or UWP knows it must update view.

Often property names are given as strings like shown here.

public GalleryItem SelectedItem
{
    get { return _selectedItem; }
    set
    {
        _selectedItem = value;
        NotifyPropertyChanged();
        NotifyPropertyChanged("SelectedItemVisibility");
        NotifyPropertyChanged("ListVisibility");
    }
}

View model classes are bigger than others because we cannot use C# automatic properties due to calls to NotifyPropertyChanged() method in setters. We have to define backing fields of properties and write all getters and setters. It’s easy to forget to update property name after it changes. Even worse – view model may call NotifyPropertyChanged() from other properties and methods that are not visible in editor near property we are changing.

Again we can use nameof operator to make build fail when we forgot to change property name in some part of view model.

public GalleryItem SelectedItem
{
    get { return _selectedItem; }
    set
    {
        _selectedItem = value;
        NotifyPropertyChanged();
        NotifyPropertyChanged(nameof(SelectedItemVisibility));
        NotifyPropertyChanged(nameof(ListVisibility));
    }
}

Now compiler will tell us if we forgot something.

Using nameof operator in ASP.NET MVC controllers

When building web applications on ASP.NET MVC we use RedirectToAction() method after some entity is added, updated or deleted. Here’s one Edit() method from web application I currently build.

[HttpPost]
public async Task<IActionResult> Edit(ReferenceEditModel model)
{
    if (!ModelState.IsValid)
    {
        await _referenceService.FillEditModelClassifies(model);

        return View("Edit", model);
    }

    await _referenceService.SaveReference(model, User.Identity.Name);

    return RedirectToAction("Index");
}

It has two code items references as string – name of view and name of action where user is redirected when data was valid and update succeeded. Using nameof operator this action will look like shown here.

[HttpPost]
public async Task<IActionResult> Edit(ReferenceEditModel model)
{
    if (!ModelState.IsValid)
    {
        await _referenceService.FillEditModelClassifies(model);

        return View(nameof(Edit), model);
    }

    await _referenceService.SaveReference(model, User.Identity.Name);

    return RedirectToAction(nameof(ReferencesController.Index));
}

Be careful with Index! I used controller class name before Index because if I leave it out then nameof operator still works even if there’s no Index() method in controller. Why? Because there is Index structure in System namespace. Be warned!

Wrapping up

Although nameof operator came to C# back in time with version 6.0 it’s still often as a hidden gem that even experienced developers discover with surprise. As we saw then nameof operator can be used in different types of applications. I agree it’s small addition to C# language and we can live without it as well but when using it we will avoid some bugs that otherwise get to production in worse case.

Liked this post? Empower your friends by sharing it!
Categories: C#
Related Post