Impostor
Impostor

Reputation: 2050

Shorten Code by accessing Dictionary with if

I have the following code

Dictionary<string, string> changesDictionary = new Dictionary<string, string>();
if (changesDictionary.ContainsKey("field1"))
{
    resultObject.field1 = changesDictionary["field1"];
}
if (changesDictionary.ContainsKey("field2"))
{
    resultObject.field2 = changesDictionary["field2"];
}
if (changesDictionary.ContainsKey("field3"))
{
    resultObject.field3 = changesDictionary["field3"];
}

which has 4 lines for a potential assignment. I'm wondering if there is a way to write it shorter.

I've tried the ternary operator which makes one line but it's harder to read.

resultObject.field1 = changesDictionary.ContainsKey("field1") ? changesDictionary["field1"] : resultObject.field1;

Upvotes: 1

Views: 164

Answers (5)

vc 74
vc 74

Reputation: 38179

Using a local function:

void SetField(string fieldName, Action<string> updater)
{
    if (changesDictionary.TryGetValue(fieldName, out string fieldValue))
    {
        updater(fieldValue);
    }
}

SetField("field1", f => resultObject.field1 = f);
SetField("field2", f => resultObject.field2 = f);
SetField("field3", f => resultObject.field3 = f);

Price to pay = readability--

Line count = 11 instead of 13

Using a local function + reflection (provided fieldx are public properties):

void SetField(string fieldName)
{
    if (changesDictionary.TryGetValue(fieldName, out string fieldValue))
    {
        PropertyInfo propertyInfo = resultObject.GetType().GetProperty(fieldName);
        propertyInfo.SetValue(resultObject, fieldValue);
    }
}

SetField("field1");
SetField("field2");
SetField("field3");

Price to pay = performance--

Line count = 12 instead of 13, but if you have 20 fields to update:

for (int i = 1; i <= 20; i++)
{
    SetField($"field{i}");
}

Much shorter

Upvotes: 1

Matthew Watson
Matthew Watson

Reputation: 109792

Assuming (given the lowercase names for the field fields) that field1, field2 and field3 are actually fields rather than properties, then you can write a local function to simplify the code as follows:

Dictionary<string, string> changesDictionary = new Dictionary<string, string>();

void update(ref string field, string key)
{
    if (changesDictionary.TryGetValue(key, out var value))
        field = value;
}

update(ref resultObject.field1, "field1");
update(ref resultObject.field2, "field1");
update(ref resultObject.field3, "field1");

Note that will NOT work if field1 etc are actually properties, because of course you can't use ref with a property.

Upvotes: 0

canton7
canton7

Reputation: 42330

You could always do something like this. It's more verbose to start, but if you have lots of properties then it might pay off:

var fields = new (string key, Action<ResultObject, string> setter)[]
{
    ("field1", (x, val) => x.field1 = val),
    ("field2", (x, val) => x.field2 = val),
    ("field3", (x, val) => x.field3 = val),
};

foreach (var (key, setter) in fields)
{
    if (changesDictionary.TryGetValue(key, out var field))
    {
        setter(resultObject, field);
    }
}

Another option is something like this:

// A local function which captures 'resultObject' and 'changesDictionary'
void Set(string key, Action<ResultObject, string> setter)
{
    if (changesDictionary.TryGetValue(key, out var field))
    {
         setter(resultObject, field);
    }
}

Set("field1", (x, val) => x.field1 = val);
Set("field2", (x, val) => x.field2 = val);
Set("field3", (x, val) => x.field3 = val);

Otherwise, if you're prepared to change your style slightly, you can do this:

if (changesDictionary.TryGetValue("field1", out var field1)) resultObject.field1 = field1;
if (changesDictionary.TryGetValue("field2", out var field2)) resultObject.field2 = field2;
if (changesDictionary.TryGetValue("field3", out var field3)) resultObject.field1 = field3;

Upvotes: 4

Timur Lemeshko
Timur Lemeshko

Reputation: 2879

If your object has FIELDS not PROPERTIES, u can use just TryGetValue to field like this

changesDictionary.TryGetValue(nameof(ResultObject.field1), out resultObject.field1);

full example:

using System;
using System.Collections.Generic;

namespace ConsoleApp27
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var resultObject = new ResultObject();
            var changesDictionary = new Dictionary<string, string>();

            changesDictionary.Add(nameof(ResultObject.field1), "q1");
            changesDictionary.Add(nameof(ResultObject.field2), "q2");
            changesDictionary.Add(nameof(ResultObject.field3), "q3");
            changesDictionary.Add(nameof(ResultObject.field4), "q4");

            changesDictionary.TryGetValue(nameof(ResultObject.field1), out resultObject.field1);
            changesDictionary.TryGetValue(nameof(ResultObject.field2), out resultObject.field2);
            changesDictionary.TryGetValue(nameof(ResultObject.field3), out resultObject.field3);
            changesDictionary.TryGetValue(nameof(ResultObject.field4), out resultObject.field4);

            Console.WriteLine(resultObject.field1);
            Console.WriteLine(resultObject.field2);
            Console.WriteLine(resultObject.field3);
            Console.WriteLine(resultObject.field4);
            Console.ReadLine();
        }

        public class ResultObject
        {
            public string field1;
            public string field2;
            public string field3;
            public string field4;
        }
    }
}

output:

q1
q2
q3
q4

Upvotes: -1

Mark Shevchenko
Mark Shevchenko

Reputation: 8207

public static class DictionaryExtensions
{
    public static TValue GetOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)
    {
        if (dictionary.TryGetValue(key, out value))
            return value;

        return defaultValue;
    }
}

. . .

resultObject.field1 = changesDictionary.GetOrDefault("field1", resultObject.field1);
resultObject.field2 = changesDictionary.GetOrDefault("field2", resultObject.field2);
resultObject.field3 = changesDictionary.GetOrDefault("field3", resultObject.field3);

Upvotes: -1

Related Questions