1

I'm a little new to C# still... I'm finding myself reusing a specific procedure over and over. Before I go writing a helper method for personal laziness, is there a shorter or less wrong way to write this sort of statement?

Dictionary<string, string> data = someBigDictionary;
string createdBy;
data.TryGetValue("CreatedBy", out createdBy);
//do that for 15 other values
...
MyEntity me = new MyEntity{
    CreatedBy = createdBy ?? "Unknown",
    //set 15 other values
    ...
}

Essentially, set a property on an object by trying to get a value, then if it's null use a default value. I have a LOT of properties, it would be better if I could just

MyEntity me = new MyEntity{
    CreatedBy = TryToGetValueOrReturnNull(data, "CreatedBy") ?? "Unknown",
    ...
}

Again, I am perfectly capable of writing my own helper function. I'm looking for an existing native functionality or shorthand before I do so.

Randy Hall
  • 7,716
  • 16
  • 73
  • 151
  • Is data a Dictionary? – mjwills Jun 06 '17 at 12:55
  • Why not provide the default value as another parameter? You can pass in null if you want - but you can pass in "Unknown" instead. – Jon Skeet Jun 06 '17 at 12:55
  • @mjwills yes, apologies I will clarify that – Randy Hall Jun 06 '17 at 12:55
  • @JonSkeet may well do that if I write my own... just showing an example – Randy Hall Jun 06 '17 at 12:56
  • 3
    If you can use C# 7 - you can do this: `CreatedBy = data.TryGetValue("CreatedBy", out var value) ? value : "Unknown"` – Evk Jun 06 '17 at 13:00
  • @Evk I cannot for this application, but that sounds like a valid answer for anyone who comes by later using C# 7 so please post – Randy Hall Jun 06 '17 at 13:01
  • IMHO it's better to leave the `CreatedBy` field blank _(dbnull)_ instead of writing a default valid _"Unknown"_ value. The UI should present "Unknown" when the `CreatedBy` field is empty. This way you can always distingues a name and _nothing_ – Jeroen van Langen Jun 06 '17 at 13:07
  • @JeroenvanLangen valid point, but this was simply an example. The default values are varied – Randy Hall Jun 06 '17 at 13:09
  • 1
    Helper function gives you advantage of abstraction so it eases future changes. Why are you trying to avoid it? – Antonín Lejsek Jun 06 '17 at 13:17
  • @AntonínLejsek I'm only trying to avoid it if there is some sort of shorthand functionality that already exists natively. I'm perfectly fine with a helper otherwise – Randy Hall Jun 06 '17 at 13:26

3 Answers3

6

There are many similar questions (like this and this) which propose different solutions from extension methods to inheriting from dictionary and overriding indexer. However they are written before C# 7, and with C# 7 you can do this in one line:

CreatedBy = data.TryGetValue("CreatedBy", out var value) ? value : "Unknown"
Evk
  • 98,527
  • 8
  • 141
  • 191
  • It appears that this is not possible without a helper method pre-C# 7, so I'm accepting this as the best answer even though I cannot use it in my specific implementation. – Randy Hall Jun 06 '17 at 13:32
  • It is possible, just clunky. string value; MyEntity me = new MyEntity{ CreatedBy = data.TryGetValue("CreatedBy", out value) ? value : "Unknown", UpdatedBy = data.TryGetValue("UpdatedBy", out value) ? value : "Unknown" //set 15 other values ... } – mjwills Jun 06 '17 at 13:51
3
public static class DictionaryExtensions
{
    public static U TryGetValueOrDefault<T, U>(this IDictionary<T, U> dict, T key, U defaultValue)
    {
        U temp;

        if (dict.TryGetValue(key, out temp))
            return temp;

        return defaultValue;
    }
}

then do something like:

Dictionary<string, string> data = someBigDictionary;
//do that for 15 other values
...
MyEntity me = new MyEntity{
    CreatedBy = data.TryGetValueOrDefault("CreatedBy", "Unknown"),
    //set 15 other values
    ...
}
mjwills
  • 23,389
  • 6
  • 40
  • 63
2

TryGetValue returns a bool indicating if the key was found in the dictionary. So you should use that and set the variable to the default if it was not found:

string createdBy;
if (!data.TryGetValue("CreatedBy", out createdBy)) createdBy="Unknown";
Ofir Winegarten
  • 9,215
  • 2
  • 21
  • 27