2

In C#, I sometimes use:

const string FirstName = "FirstName";
const string SSN = "SSN";

...

var ssn = GetValue(key: SSN);  // e.g. GetValue fetches value from some key/value store

to avoid hard-coding key strings throughout my code. I'm thinking of taking advantage of C# 6.0 nameof to avoid the repetition in the const declaration, like so:

const object FirstName = null;
const object SSN = null;

...

var ssn = GetValue(key: nameof(SSN));

Is this a proper use of nameof? Is there a better way to avoid repetition in const declarations?

  • 2
    It has the huge disadvantage that now renaming your variable will destroy persistent data. – gnasher729 Apr 22 '16 at 8:23
3

How about an enumeration? (thanks to @JoelFan for pointing out the Enum ToString method)

var value = GetValue(Keys.SSN.ToString());

And of course you would define an enumeration with each of your keys.

enum Keys
{
    SSN, FirstName 
}
  • 1
    Why do you need an extension method like that? Can't you just call ToString on any Enum? – JoelFan Apr 22 '16 at 1:29
  • 1
    Huh. looks like you can - I'm not working on the project where we did that before so I can't go check to see if I'm remembering something wrong or we were out to lunch. Anyway you're right, no need for the extension method. – alexanderbird Apr 22 '16 at 2:46
  • Surely this has exactly the same weakness as using nameof: refactoring the name of any of the enum's members will break any persisted data structure that uses the old string values. I'm not saying don't use this technique, just to be aware of the tradeoffs (ie. don't use if you're planning on persisting these enum values anywhere). – Steven Rands Sep 28 '16 at 12:41
  • Yes, you're right. However, I think a well placed comment could do the trick - it's just a matter of communicating with all future devs that the enum needs to match the data storage. There would be other clues, like if you named the enum KeysForTheDataStorage, or a quick check of the usages shows that it's always used for GetValue(KeysForTheDataStorage.SSN.ToString()). The bottom line is that string keys for value lookup in a strongly typed language will be somewhat brittle no matter what you do. – alexanderbird Sep 28 '16 at 14:09
3

No. You've made the contract of the SSN constant really weak- it's completely non-obvious what it's for.

You could use nameof in the definition but that would still look pretty similar to your original code.

const string FirstName = nameof(FirstName);
const string SSN = nameof(SSN);
1

Someone else has mentioned this, but I really think an Enum is the tool for the job here. Here is a detailed explanation of when and why they can be useful. It's a good design choice over many other constant/key options for performance, extensibility, readability, etc.

If I understand what you're trying to do, an Enum is doing exactly what you intend with your off-label use of nameof: A constant that is only a name. I like the term "strongly-typed constant" to describe the concept of an Enum. Off the top of my head...

// Note: Enum names should describe a generic member, so avoid names like IDs/KeyCollection/PersonalData
public Enum Identifier
{
 FirstName, SSN, Fingerprint, Retina, OtherKey, FinalKey
}
// ...
var ssn = GetValue(SSN);

// Other considerations vs const string keys:
string[] AllMyConstants = Enum.GetNames(typeof(Identifier)); // Collections and parsing to/from strings built-in
////Identifier.SSN = "Compiler error will save me from trying to change a constant."

// Bonus thing I just learned: System.Enum uses ints underneath, so you can get imaginative defining enums as ints:
public Enum BasketballPosition {PG = 1, SG = 2, SF = 3, PF = 4, C = 5};
public Enum Grade {F = 0, D = 60, C = 70, B = 80, A = 90};  
public Enum DifficultyFactor {Easy = 1, Medium = 10, Hard = 100, Insane = 1000};
public Enum Transaction {Deposit = 1, Withdrawal = -1, Transfer = 0};
public Enum MilestoneDay {Conceived = -270, Born = 0, FirstBirthday = 365, EighteenthBirthday = 6570}; 

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.