C# Tip: do NOT use nameof to give constants a value
In C#, nameof can be quite useful. But it has some drawbacks, if used the wrong way.
Table of Contents
Just a second! π«·
If you are here, it means that you are a software developer. So, you know that storage, networking, and domain management have a cost .
If you want to support this blog, please ensure that you have disabled the adblocker for this site. I configured Google AdSense to show as few ADS as possible - I don't want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.
Thank you for your understanding.
- Davide
As per Microsoft’s definition,
A
nameof
expression produces the name of a variable, type, or member as the string constant.
This means that you can have, for example
void Main()
{
PrintItems("hello");
}
public void PrintItems(string items)
{
Console.WriteLine(nameof(items));
}
that will print “items”, and not “hello”: this is because we are printing the name of the variable, items, and not its runtime value.
A real example I saw in my career
In some of the projects I’ve worked on during these years, I saw an odd approach that I highly recommend NOT to use: populate constants with the name of the constant itself:
const string User_Table = nameof(User_Table);
and then use the constant name to access stuff on external, independent systems, such as API endpoints or Databases:
const string User_Table = nameof(User_Table);
var users = db.GetAllFromTable(User_Table);
The reasons behind this, in my teammates opinion, are that:
- It’s easier to write
- It’s more performant: we’re using constants that are filled at compile time, not at runtime
- You can just rename the constant if you need to access a new database table.
I do not agree with them: expecially the third point is pretty problematic.
Why this approach should not be used
We are binding the data access to the name of a constant, and not to its value.
We could end up in big trouble because if, from one day to the next, the system might not be able to reach the User table because the name does not exist.
How is it possible? It’s a constant, it can’t change! No: it’s a constant whose value changes if the contant name changes.
It can change for several reasons:
- A developer, by mistake, renames the constant. For example, from
User_Table
toUsers_Table
. - An automatic tool (like a Linter) with wrong configurations updates the constants’ names: from
User_Table
toUSER_TABLE
. - New team styleguides are followed blindly: if the new rule is that “constants must not contain hyphens” and you apply it everywhere, you’ll end in trouble.
To me, those are valid reasons not to use nameof
to give a value to a constant.
How to overcome it
If this approach is present in your codebase and it’s too time-consuming to update it everywhere, not everything is lost.
You must absolutely do just one thing to prevent all the issues I listed above: add tests, and test on the actual value.
If you’re using Moq, for instance, you should test the database access we saw before as:
// initialize and run the method
[...]
// test for the Table name
_mockDb.Verify(db => db.GetAllFromTable("User_Table"));
Notice that here you must test against the actual name of the table: if you write something like
_mockDb.Verify(db => db.GetAllFromTable(It.IsAny<string>()));
or
_mockDb.Verify(db => db.GetAllFromTable(DbAccessClass.User_Table));
//say that DbAccessClass is the name of the class the uses the data access showed above
the whole test becomes pointless.
Further readings
This article lies in the middle of my C# tips π and my Clean Code tips π.
This article first appeared on Code4IT π§
Wrapping up
In this article, we’ve learned that you could value a constant with its own name, using nameof
, but also that you shouldn’t.
Have you ever seen this approach? In your opinion, what are some other benefits and disadvantages of it? Drop a comment below! π©
I hope you enjoyed this article! Let’s keep in touch on Twitter or on LinkedIn, if you want! π€π€
Happy coding!
π§