365

Version 6.0 got a new feature of nameof, but I can't understand the purpose of it, as it just takes the variable name and changes it to a string on compilation.

I thought it might have some purpose when using <T> but when I try to nameof(T) it just prints me a T instead of the used type.

Any idea on the purpose?

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
atikot
  • 4,761
  • 4
  • 26
  • 34
  • 3
    See also https://msdn.microsoft.com/library/dn986596.aspx – Corak Jul 29 '15 at 09:08
  • 30
    There wasn't a way to get that `T` before. There was a way to get the used type before. – Jon Hanna Jul 29 '15 at 09:10
  • 20
    Definitely useful when refactory/renaming the name within `nameof`. Also helps to prevent typos. – bvj May 11 '17 at 18:17
  • nameof comes in handy with nunit 3 [TestCaseData](https://github.com/nunit/docs/wiki/TestCaseData). The docs show a method name by string `[Test, TestCaseSource(typeof(MyDataClass), "TestCases")]`, which can be replaced with `[Test, TestCaseSource(typeof(MyDataClass), nameof(MyDataClass.TestCases))]`. Much nicer. – Jeremy Mar 05 '18 at 14:54
  • 4
    The official documentation of *nameof* has moved to here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/nameof - It also lists key use cases which serve as a pretty good answer to the question. – markus s Apr 20 '18 at 06:40

17 Answers17

421

What about cases where you want to reuse the name of a property, for example when throwing exception based on a property name, or handling a PropertyChanged event. There are numerous cases where you would want to have the name of the property.

Take this example:

switch (e.PropertyName)
{
    case nameof(SomeProperty):
    { break; }

    // opposed to
    case "SomeOtherProperty":
    { break; }
}

In the first case, renaming SomeProperty will cause a compilation error if you don't change both the property definition and the nameof(SomeProperty) expression. In the second case, renaming SomeOtherProperty or altering the "SomeOtherProperty" string will result in silently broken runtime behavior, with no error or warning at build time.

This is a very useful way to keep your code compiling and bug free (sort-of).

(A very nice article from Eric Lippert why infoof didn't make it, while nameof did)

Tim Sparkles
  • 771
  • 6
  • 21
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • 2
    I understand the point, just adding that resharper changes the strings when refactoring names, not sure if VS has similar functionality. – Ash Burlaczenko Jul 29 '15 at 11:26
  • 12
    It has. But both Resharper and VS don't work over projects for example. This does. In fact, this is the better solution. – Patrick Hofman Jul 29 '15 at 11:28
  • 60
    Another common use case is routing in MVC using `nameof` and the action's name instead of a hard-coded string. – RJ Cuthbertson Jul 29 '15 at 14:21
  • @RJCuthbertson Very logical but what about using nameof on views for action name? Controller class isn't static so that we cannot get the action name, any simple solution for this too?? – yakya Oct 24 '16 at 18:22
  • 2
    @sotn I'm not sure I understand what you're asking. There's nothing stopping you from using it like `public class MyController { public ActionResult Index() { return View(nameof(Index)); } }` - and you can use `nameof` on non-static members (for instance you can call `nameof(MyController.Index)` using the class above and it will emit "Index"). Check out the examples at https://msdn.microsoft.com/en-us/library/dn986596.aspx?f=255&MSPPError=-2147217396 – RJ Cuthbertson Oct 24 '16 at 19:56
  • @RJCuthbertson wow accessing non-static method name without an instance?? that's some hardcore compiler logic lol – yakya Oct 25 '16 at 07:36
  • 2
    I don't see why that is special. Variable names are always the same, right? Whether you have an instance or not, the variable names won't change @sotn – Patrick Hofman Oct 25 '16 at 07:37
  • @PatrickHofman Variable names maybe but what about method names? You can use `nameof` with method names too. Assume that I have an Action in MVC application named Index and I want to change it's name because I want my users to access the site as '/MyController/Home/' and also don't want to do it by using a Route Attribute and just rename it as "Home". Searching for "Index" and replacing it with "Home" in whole project can take lots of time.. – yakya Oct 25 '16 at 07:56
  • 2
    @PatrickHofman And I'm not sure I understand what you described. But if you meant what's so special about using `nameof` on non-static method names? Well, in a cshtml file for example; we don't have access to Controller instance and we use lots of urls etc. by using UrlHelpers like `Url.Action("Index")` etc. Therefore, it means that we can use `Url.Action(nameof(HomeController.Index))`. And when we rename it in the future and turn the view compilation on, we can rename the action names easily.. Using it without an instance is big imo.. – yakya Oct 25 '16 at 08:05
  • 2
    Not if you understand this is all done on compile time. There aren't instances at that time yet, just code @sotn – Patrick Hofman Oct 25 '16 at 08:06
  • 1
    @PatrickHofman lol of course it is. nameof has no effect on the generated IL etc. But, I think that it is a nice little thing that can ease your job a little.. – yakya Oct 25 '16 at 08:15
  • In case anyone's wondering what happens if `SomeProperty` gets renamed `SomeOtherProperty`, you get a compilation error: https://learn.microsoft.com/en-us/dotnet/csharp/misc/cs0152 – JohnLBevan Oct 02 '18 at 15:31
218

It's really useful for ArgumentException and its derivatives:

public string DoSomething(string input) 
{
    if(input == null) 
    {
        throw new ArgumentNullException(nameof(input));
    }
    ...

Now if someone refactors the name of the input parameter the exception will be kept up to date too.

It is also useful in some places where previously reflection had to be used to get the names of properties or parameters.

In your example nameof(T) gets the name of the type parameter - this can be useful too:

throw new ArgumentException(nameof(T), $"Type {typeof(T)} does not support this method.");

Another use of nameof is for enums - usually if you want the string name of an enum you use .ToString():

enum MyEnum { ... FooBar = 7 ... }

Console.WriteLine(MyEnum.FooBar.ToString());

> "FooBar"

This is actually relatively slow as .Net holds the enum value (i.e. 7) and finds the name at run time.

Instead use nameof:

Console.WriteLine(nameof(MyEnum.FooBar))

> "FooBar"

Now .Net replaces the enum name with a string at compile time.


Yet another use is for things like INotifyPropertyChanged and logging - in both cases you want the name of the member that you're calling to be passed to another method:

// Property with notify of change
public int Foo
{
    get { return this.foo; }
    set
    {
        this.foo = value;
        PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.Foo));
    }
}

Or...

// Write a log, audit or trace for the method called
void DoSomething(... params ...)
{
    Log(nameof(DoSomething), "Message....");
}
Keith
  • 150,284
  • 78
  • 298
  • 434
  • 10
    And you've put another cool feature in: string interpolation! – Patrick Hofman Jul 29 '15 at 09:14
  • 1
    @PatrickHofman and `typeof(T)`, which is another piece of compile-time sugar that's useful in similar circumstances :-) – Keith Jul 29 '15 at 09:18
  • 1
    One thing that i'm missing is something like `nameofthismethod`. You can use `Log.Error($"Error in {nameof(DoSomething)}...")` but if you copy-paste this to other methods you won't notice that it's still referring to `DoSomething`. So while it's working perfectly with local variables or parameters the method-name is a problem. – Tim Schmelter Jul 21 '16 at 08:48
  • 3
    Do you know if `nameOf` will use the `[DisplayName]` attribute if present? For the `enum` example I use `[DisplayName]` often with MVC projects – Luke T O'Brien Jun 15 '17 at 15:20
  • @Keith What did you find out? There's also the `[Description]` attribute. It would be nice to give args to the `nameOf`, for eg deciding to return the type FullName instead of Name when using `nameOf(System.String)` – Luke T O'Brien Jun 15 '17 at 16:34
  • @LukeTO'Brien ah, no, I thought you were saying that it did. I think nameof always gets the actual name, ignoring any attributes. – Keith Jun 15 '17 at 16:37
  • Unfortunately a developer tried to follow the first `ArgumentException` pattern but generalized to all exceptions, so all my catch blocks are sprinkled with `throw new Exception(nameof(ex))` which hides the actual exception and just logs "ex". The answer has good examples, but make sure you understand them before you try to apply them. – AaronLS Jul 23 '19 at 23:17
  • 2
    @AaronLS Yes, it's fairly specialised and not something that you would use often. However that `throw new` is a whole other anti-pattern - I find over-using `catch` to be a common problem with junior devs because it feels like fixing the problem (when most of the time it's just hiding it). – Keith Jul 24 '19 at 14:27
36

Another use-case where nameof feature of C# 6.0 becomes handy - Consider a library like Dapper which makes DB retrievals much easier. Albeit this is a great library, you need to hardcode property/field names within query. What this means is that if you decide to rename your property/field, there are high chances that you will forget to update query to use new field names. With string interpolation and nameof features, code becomes much easier to maintain and typesafe.

From the example given in link

without nameof

var dog = connection.Query<Dog>(
    "select Age = @Age, Id = @Id",
    new {Age = (int?) null, Id = guid});

with nameof

var dog = connection.Query<Dog>(
    $"select {nameof(Dog.Age)} = @Age, {nameof(Dog.Id)} = @Id",
    new {Age = (int?) null, Id = guid});
Genusatplay
  • 761
  • 1
  • 4
  • 15
Sateesh Pagolu
  • 9,282
  • 2
  • 30
  • 48
  • 11
    I love Dapper and I really like string interporlations, but IMO this looks so ugly. The risk of breaking a query by renaming a column seems so small compared to such ugly queries. At first sight I'd say I prefer writing EF LINQ queries, or following a convention like [TableName].[ColumnName] where I can easily find/replace my queries when I need. – drizin Nov 14 '19 at 06:51
  • @drizin I use [Dapper FluentMap](https://dapper-tutorial.net/dapper-fluentmap) to prevent such queries (and also for separation of concerns) – mamuesstack Apr 21 '20 at 05:23
30

Your question already expresses the purpose. You must see this might be useful for logging or throwing exceptions.

For example:

public void DoStuff(object input)
{
    if (input == null)
    {
        throw new ArgumentNullException(nameof(input));
    }
}

This is good. If I change the name of the variable, the code will break instead of returning an exception with an incorrect message.


Of course, the uses are not limited to this simple situation. You can use nameof whenever it would be useful to code the name of a variable or property.

The uses are manifold when you consider various binding and reflection situations. It's an excellent way to bring what were run time errors to compile time.

Pang
  • 9,564
  • 146
  • 81
  • 122
Jodrell
  • 34,946
  • 5
  • 87
  • 124
  • for logging i could just write the name of the variable myself, would be shorter – atikot Jul 29 '15 at 09:09
  • 8
    @atikot: But then, if you rename the variable, the compiler won't notice that the string doesn't match any more. – O. R. Mapper Jul 29 '15 at 09:09
  • 1
    I actually use resharper which takes it to account, but i see your point. – atikot Jul 29 '15 at 09:11
  • 4
    @atikot, so do I, but Resharper only generates a warning, not a compiler error. There's a difference between a certainty and good advice. – Jodrell Jul 29 '15 at 09:12
  • 1
    @atikot, and, Resharper doesn't check logging messages – Jodrell Jul 29 '15 at 09:14
  • 2
    @Jodrell: And, I suspect, it doesn't check various other uses, either - how about WPF bindings created in code-behind, custom `OnPropertyChanged` methods (that directly accept property names rather than `PropertyChangedEventArgs`), or calls to reflection to look for a particular member or type? – O. R. Mapper Jul 29 '15 at 09:19
14

The most common use case I can think of is when working with the INotifyPropertyChanged interface. (Basically everything related to WPF and bindings uses this interface)

Take a look at this example:

public class Model : INotifyPropertyChanged
{
    // From the INotifyPropertyChanged interface
    public event PropertyChangedEventHandler PropertyChanged;

    private string foo;
    public String Foo
    {
        get { return this.foo; }
        set
        {
            this.foo = value;
            // Old code:
            PropertyChanged(this, new PropertyChangedEventArgs("Foo"));

            // New Code:
            PropertyChanged(this, new PropertyChangedEventArgs(nameof(Foo)));           
        }
    }
}

As you can see in the old way we have to pass a string to indicate which property has changed. With nameof we can use the name of the property directly. This might not seem like a big deal. But image what happens when somebody changes the name of the property Foo. When using a string the binding will stop working, but the compiler will not warn you. When using nameof you get a compiler error that there is no property/argument with the name Foo.

Note that some frameworks use some reflection magic to get the name of the property, but now we have nameof this is no longer neccesary.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
Roy T.
  • 9,429
  • 2
  • 48
  • 70
  • 8
    Whilst this is a valid approach, a more convenient (and DRY) approach is to use the `[CallerMemberName]` attribute on a new method's param to raise this event. – Drew Noakes Jul 29 '15 at 22:18
  • 1
    I agree CallerMemberName is also nice, but its a separate use case, since (as you said) you can only use it in methods. As for DRY, I'm not sure if `[CallerMemberName]string x = null` is better than `nameof(Property)`. You could say the property name is used twice, but thats basically the argument passed to a function. Not really what is meant with DRY I think :). – Roy T. Jul 30 '15 at 06:46
  • Actually you can use it in properties. They are members too. The benefit over `nameof` is that the property setter needn't specify the property name at all, eliminating the possibility of copy/paste bugs. – Drew Noakes Jul 30 '15 at 07:44
  • 7
    It's a 'better together' situation for `INotifyPropertyChanged`, using the `[CallerMemberNameAttribute]` allows the change notification to be cleanly raised from a property setter, while the `nameof` syntax allows a change notification to be cleanly raised from a different location in your code. – Andrew Hanlon Jul 30 '15 at 13:16
12

Most common usage will be in input validation, such as

//Currently
void Foo(string par) {
   if (par == null) throw new ArgumentNullException("par");
}

//C# 6 nameof
void Foo(string par) {
   if (par == null) throw new ArgumentNullException(nameof(par));
}

In first case, if you refactor the method changing par parameter's name, you'll probably forget to change that in the ArgumentNullException. With nameof you don't have to worry about that.

See also: nameof (C# and Visual Basic Reference)

Massimo Prota
  • 1,226
  • 7
  • 14
9

Let's say you need to print the name of a variable in your code. If you write:

int myVar = 10;
print("myVar" + " value is " + myVar.toString());

and then if someone refactors the code and uses another name for myVar, he/she would have to look for the string value in your code and change it accordingly.

Instead, if you write:

print(nameof(myVar) + " value is " + myVar.toString());

It would help to refactor automatically!

Pang
  • 9,564
  • 146
  • 81
  • 122
cnom
  • 3,071
  • 4
  • 30
  • 60
  • I wish there had been a special variable-parameter syntax which would pass an array of tuples, one for each parameter, containing the source code representation, the `Type`, and the value. That would make it possible for code invoking logging methods to eliminate a lot of redundancy. – supercat Jul 29 '15 at 16:07
9

The ASP.NET Core MVC project uses nameof in the AccountController.cs and ManageController.cs with the RedirectToAction method to reference an action in the controller.

Example:

return RedirectToAction(nameof(HomeController.Index), "Home");

This translates to:

return RedirectToAction("Index", "Home");

and takes takes the user to the 'Index' action in the 'Home' controller, i.e. /Home/Index.

Fred
  • 12,086
  • 7
  • 60
  • 83
  • Why not go whole-hog and use `return RedirectToAction(nameof(HomeController.Index), nameof(HomeController).Substring(nameof(HomeController),0,nameof(HomeController).Length-"Controller".Length));` ? – Suncat2000 Nov 03 '17 at 19:02
  • @Suncat2000 because one of those things is done in compilation and the other isn't? :) – Dinerdo Aug 16 '18 at 16:42
7

The MSDN article lists MVC routing (the example that really clicked the concept for me) among several others. The (formatted) description paragraph reads:

  • When reporting errors in code,
  • hooking up model-view-controller (MVC) links,
  • firing property changed events, etc.,

you often want to capture the string name of a method. Using nameof helps keep your code valid when renaming definitions.

Before you had to use string literals to refer to definitions, which is brittle when renaming code elements because tools do not know to check these string literals.

The accepted / top rated answers already give several excellent concrete examples.

Community
  • 1
  • 1
brichins
  • 3,825
  • 2
  • 39
  • 60
6

As others have already pointed out, the nameof operator does insert the name that the element was given in the sourcecode.

I would like to add that this is a really good idea in terms of refactoring since it makes this string refactoring safe. Previously, I used a static method which utilized reflection for the same purpose, but that has a runtime performance impact. The nameof operator has no runtime performance impact; it does its work at compile time. If you take a look at the MSIL code you will find the string embedded. See the following method and its disassembled code.

static void Main(string[] args)
{
    Console.WriteLine(nameof(args));
    Console.WriteLine("regular text");
}

// striped nops from the listing
IL_0001 ldstr args
IL_0006 call System.Void System.Console::WriteLine(System.String)
IL_000C ldstr regular text
IL_0011 call System.Void System.Console::WriteLine(System.String)
IL_0017 ret

However, that can be a drawback if you plan to obfuscate your software. After obfuscation the embedded string may no longer match the name of the element. Mechanisms that rely on this text will break. Examples for that, including but not limited to are: Reflection, NotifyPropertyChanged ...

Determining the name during runtime costs some performance, but is safe for obfuscation. If obfuscation is neither required nor planned, I would recommend using the nameof operator.

Sildoreth
  • 1,883
  • 1
  • 25
  • 38
cel sharp
  • 149
  • 9
3

The purpose of the nameof operator is to provide the source name of the artifacts.

Usually the source name is the same name as the metadata name:

public void M(string p)
{
    if (p == null)
    {
        throw new ArgumentNullException(nameof(p));
    }
    ...
}

public int P
{
    get
    {
        return p;
    }
    set
    {
        p = value;
        NotifyPropertyChanged(nameof(P));
    }
}

But this may not always be the case:

using i = System.Int32;
...
Console.WriteLine(nameof(i)); // prints "i"

Or:

public static string Extension<T>(this T t)
{
    return nameof(T); returns "T"
}

One use I've been giving to it is for naming resources:

[Display(
    ResourceType = typeof(Resources),
    Name = nameof(Resources.Title_Name),
    ShortName = nameof(Resources.Title_ShortName),
    Description = nameof(Resources.Title_Description),
    Prompt = nameof(Resources.Title_Prompt))]

The fact is that, in this case, I didn't even need the generated properties to access the resources, but now I have a compile time check that the resources exist.

cel sharp
  • 149
  • 9
Paulo Morgado
  • 14,111
  • 3
  • 31
  • 59
2

The purpose of nameof is refactoring. For example when you change the name of a class to which you refer to through nameof somewhere else in your code you will get a compilation error which is what you want. If you didn't use nameof and had just a plain string as a reference you'd have to fulltext search for the name of the class in order to change it. That's a pain in the bottom. With nameof you can rest easy, build, and get all the cases for change automatically in your IDE.

Audwin Oyong
  • 2,247
  • 3
  • 15
  • 32
mucomoc
  • 159
  • 2
  • 6
1

Another use case of nameof is to check tab pages, instead of checking the index you can check the Name property of the tabpages as follow:

if(tabControl.SelectedTab.Name == nameof(tabSettings))
{
    // Do something
}

Less messy :)

diedrop
  • 68
  • 1
  • 8
1

I find that nameof increases the readability of very long and complex SQL statements in my applications. It makes the variables stand out of that sea of strings and eliminates your job of figuring out where the variables are used in your SQL statements.

public bool IsFooAFoo(string foo, string bar)
{
    var aVeryLongAndComplexQuery = $@"SELECT yada, yada
    -- long query in here
    WHERE fooColumn = @{nameof(foo)}
    AND barColumn = @{nameof(bar)}
    -- long query here";


    SqlParameter[] parameters = {
        new SqlParameter(nameof(foo), SqlDBType.VarChar, 10){ Value = foo },
        new SqlParameter(nameof(bar), SqlDBType.VarChar, 10){ Value = bar },
    }
}
0

One of the usage of nameof keyword is for setting Binding in wpf programmatically.

to set Binding you have to set Path with string, and with nameof keyword, it's possible to use Refactor option.

For example, if you have IsEnable dependency property in your UserControl and you want to bind it to IsEnable of some CheckBox in your UserControl, you can use these two codes:

CheckBox chk = new CheckBox();
Binding bnd = new Binding ("IsEnable") { Source = this };
chk.SetBinding(IsEnabledProperty, bnd);

and

CheckBox chk = new CheckBox();
Binding bnd = new Binding (nameof (IsEnable)) { Source = this };
chk.SetBinding(IsEnabledProperty, bnd);

It's obvious the first code can't refactor but the secend one...

Mehdi Khademloo
  • 2,754
  • 2
  • 20
  • 40
0

Previously we were using something like that:

// Some form.
SetFieldReadOnly( () => Entity.UserName );
...
// Base form.
private void SetFieldReadOnly(Expression<Func<object>> property)
{
    var propName = GetPropNameFromExpr(property);
    SetFieldsReadOnly(propName);
}

private void SetFieldReadOnly(string propertyName)
{
    ...
}

Reason - compile time safety. No one can silently rename property and break code logic. Now we can use nameof().

QtRoS
  • 1,149
  • 1
  • 16
  • 23
0

It has advantage when you use ASP.Net MVC. When you use HTML helper to build some control in view it uses property names in name attribure of html input:

@Html.TextBoxFor(m => m.CanBeRenamed)

It makes something like that:

<input type="text" name="CanBeRenamed" />

So now, if you need to validate your property in Validate method you can do this:

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
  if (IsNotValid(CanBeRenamed)) {
    yield return new ValidationResult(
      $"Property {nameof(CanBeRenamed)} is not valid",
      new [] { $"{nameof(CanBeRenamed)}" })
  }
}

In case if you rename you property using refactoring tools, your validation will not be broken.

dgtlfx
  • 101
  • 1
  • 7