Only create dictionary once - and use that when dictionary is being called? - c#

I am currently working on refactoring some code, where I have stumbled upon this static dictionary:
public static Dictionary<string, string> CountryNamesAndCodes()
{
var dictionary = new Dictionary<string, string>();
dictionary.Add("AF", "Afghanistan");
dictionary.Add("AL", "Albania");
dictionary.Add("DZ", "Algeria");
dictionary.Add("AD", "Andorra");
dictionary.Add("AO", "Angola");
dictionary.Add("AG", "Antigua and Barbuda");
dictionary.Add("AR", "Argentina");
dictionary.Add("AM", "Armenia");
...
}
Which first of all is defined in the service layer, and takes up a lot a space - 400 lines, and eventhough it is static, it seem to always recreate the dictionary, meaning making the static part of it redundant - or am I wrong?
how do I ensure that this is only created once, and everytime I call it, it make use of the same instance.

You are quite right, you can extract the local dictionary as a static member
I suggest something like this (field):
// static readonly (we want to create it once) field of
// IReadOnlyDictionary type - we want to read key value pairs after its creation
private static readonly IReadOnlyDictionary<string, string> countries =
// We may want to be nice and let ignore case for keys
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) {
{ "AF", "Afghanistan" },
{ "AL", "Albania" },
{ "DZ", "Algeria" },
//TODO:Put all the other records here
};
or like this (property):
// static readonly (there's no "set") property of
// IReadOnlyDictionary type - we want just to read key value pairs after its creation
private static IReadOnlyDictionary<string, string> Countries { get; } =
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) {
{ "AF", "Afghanistan" },
{ "AL", "Albania" },
{ "DZ", "Algeria" },
//TODO:Put all the other records here
};

public static class Globals
{
static Dictionary<string, string>
CountryNamesAndCodes = new Dictionary<string, string>
{
{"AF", "Afghanistan"},
{"AL", "Albania"}
};
}
name = Globals.CountryNamesAndCodes["AF"];

Related

Is there a way to convert static string class property to Dictionary in C#?

public static class somename
{
public const string abc = "abc 1";
public const string xyz = "xyz 2";
public const string vhj = "vhj 3";
}
I wanted to convert this into dictionary object and use this in foreach
Any idea?
You can declare a static readonly dictionary with an initializer, if that's what you mean:
public static readonly Dictionary<string, string> MyDict =
new Dictionary<string, string> {{"abc", "abc 1"}, {"xyz", "xyz 2"}, {"vhj", "vhj 3"}};
To generate it from the class you already have, you need to use reflection:
var constants = typeof(somename).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
.Where(fi => fi.IsLiteral && !fi.IsInitOnly && fi.FieldType==typeof(string));
var myDict = new Dictionary<string, string>();
foreach (var c in constants)
{
myDict.Add(c.Name, (string)c.GetRawConstantValue());
}
You can't create const dictionary, but you can do it readonly:
public static class somename {
// We can't assign MyDictionary (readonly)
// We can't add, remove or change items (IReadOnlyDictionary)
public static readonly IReadOnlyDictionary<string, string> MyDictionary = new Dictionary<string, string>() {
{ "abc", "abc 1" },
{ "xyz", "xyz 2" },
{ "vhj", "vhj 3" },
};
}
I've exposed IReadOnlyDictionary<string, string> to prevent unwanted chageing like
somename.MyDictionary["abc"] = "pqr" // typo: `=` instead of `==`
If you want elaborated logic, you can put it into static constructor:
public static class somename {
public static readonly IReadOnlyDictionary<string, string> MyDictionary;
static someone() {
Dictionary<string, string> myDict = new();
myDict.Add("abc", ComputeAbc());
myDict.Add("xyz", ComputeXyz());
myDict.Add("vhj", ComputeVhj());
MyDictionary = myDict;
}
}
You can enumerate {Key, Value} pairs in foreach, e.g.
foreach (var pair in somename.MyDictionary) {
Console.WriteLine($"{pair.Key} == {pair.Value}");
}
As it was stated by many people on this thread you can't really map your static class with const fields to a dictionary with the same runtime guarantees. In order to understand the problem let's define three terms:
Const: It has a compile-time guarantee that its value can't be changed.
Readonly: It has a run-time guarantee that once it is initialized it can't be changed.
Immutable: It has a run-time guarantee that whenever you perform a modification operation then it creates a new version of the object.
Please also bear in mind that objects and collections are treated in a different way. For example if you mark a collection as readonly it means you can't change the reference of the collection to another collection or to null. But it does not prevent you to add/remove items to/from the collection.
That's there are ReadonlyDictionary and ImmutableDictionary.
The closest thing what you can get is to use ImmutableDictionary as an implementation and expose it as an IReadonlyDictionary.
public readonly IReadOnlyDictionary<string, string> somenames = new Dictionary<string, string>
{
{ "abc", "abc 1" },
{ "xyz", "xyz 2" },
{ "vhj", "vhj 3" }
}.ToImmutableDictionary();
There are several ways to build an immutable collections. Here I have listed a couple of options.

how to get corresponding "Name"

I have a C# dictionary in which I have a corresponding NAME against the ID.
Dictionary<string, List<object>> dict = new Dictionary<string, List<object>>
{
{ "ID", new List<object> { "Id1", "Id2" } },
{ "NAME", new List<object> { "True", "False" } }
};
foreach (var id in dict["ID"])
{
Console.WriteLine(id);
//how to get corresponding "Name". For "Id1" = "True" and for "Id2" = "False"
}
In above code I loop through ID, but how to get corresponding NAME?
I think a better design would be to create a class with the two properties and then iterate. If you find yourself having to sync different data structures for simple data representations then I'd suggest rethinking the design.
public class MyClass
{
public string Id { get; set; }
public bool Name { get; set; }
}
And then hold a List<MyClass> which when you iterate:
foreach (var item in list)
{
// Now access item.Id, item.Name
}
The use of dictionaries is good when you have some sort of natural key for your data and you want to access access an item by that key. As the items are accessed via a hash function accessing by key is done in O(1) whereas searching in a list is O(n). However in your case you are iterating all items in any case so no need for dictionary and arranging the data in a class is a better design.
A bit about the differences and some references:
what is the difference between list<> and dictionary<> in c#
List vs ArrayList vs Dictionary vs Hashtable vs Stack vs Queue?
If you do have control over dictionary data it's best to either use Gilad's answer and store everything in List<MyClass> or to use Dictionary<string, bool> :
Dictionary<string, bool> dict = new Dictionary<string, bool>()
{
{ "Id1", true }, { "Id2", false },
};
But if you do not have control over format of this data and get it as a dictionary from somewhere (for example web service) you could utilize .Zip method to convert this dictionary into one list of either anonymous objects/custom class or Tuples, where Item1 is Id and Item2 is value:
// anonymous object
var data = dict["ID"].Zip(dict["NAME"], (x, y) => new
{
ID = x,
NAME = y
}).ToList();
// tuple
// List<Tuple<object, object>> data = dict["ID"].Zip(dict["NAME"], Tuple.Create).ToList();
foreach (var obj in data)
{
Console.WriteLine(obj.ID + " " obj.NAME);
}
The other answers are probably what you should do to better structure your code. However, if you need to stick to your original use case, you could do something like this:
//Depending on what you're dealing with: Dictionary<string, List<string>>
Dictionary<string, List<object>> dict = new Dictionary<string, List<object>>{
{"ID", new List<object>{"Id1", "Id2"}},
{"NAME", new List<object>{"True", "False"}}
};
foreach(var v in dict.Keys){
Console.WriteLine($"{v} = {string.Join(",", dict[v])}");
}
//Output:
//ID = Id1,Id2
//NAME = True,False
Even if you have the just the mapping of ID and Name you can have very simple variable
Dictionary<string,string> lookup = new Dictionary<string,string>();
lookup.Add("ID1","True")
and if Name is Boolean type then replace string to bool in the
Dictionary<string,bool> lookup = new Dictionary<string,bool>();

Automapper Update Dictionary Values

I have an Entity that contains a dictionary, and what i want to achieve is that automapper not simply Replace the dictionary but updates it's values.
class ExampleClass
{
public string Name { get; set; }
public Dictionary<int, string[]> Dictionary { get; set; }
}
Mapper.CreateMap<ExampleClass, ExampleClass>().ForAllMembers(opt => opt.Condition(srs => !srs.IsSourceValueNull));
var originalClass = new ExampleClass();
originalClass.Name = "Original Class";
originalClass.Dictionary = new Dictionary<int, string[]>
{
{0, new []{"V1", "V2", "V3"}},
{1, new []{"V1", "V2", "V3"}},
{2, new []{"V1", "V2", "V3"}}
};
var newelyCreatedClass = new ExampleClass();
newelyCreatedClass.Dictionary = new Dictionary<int, string[]>
{
{1, new []{"E1", "E2", "E9"}},
};
Mapper.Map(newelyCreatedClass, originalClass);
In the above code, automapper strangely doesn't update the Dictionary element with key == 1 but replaces the whole original one with the one created in newelyCreatedClass .
AutoMapper just automatically compares and sets values if they exist, this is why the property is getting overwritten. But what you can do is use an automapper feature called Custom Value Resolvers.
Then you could just write a resolver to check the dictionary and its values.
public class CustomResolver : IValueResolver<ExampleClass, ExampleClass, Dictionary<int, string[]>>
{
public Dictionary<int, string[]> Resolve(ExampleClass source, ExampleClass destination, Dictionary<int, string[]> member, ResolutionContext context)
{
// logic to iterate through the dictionarys and resolve into dictionary containing values that you want.
}
}

Looping through dictionary object

I am very new to .NET, used to working in PHP. I need to iterate via foreach through a dictionary of objects. My setup is an MVC4 app.
The Model looks like this:
public class TestModels
{
Dictionary<int, dynamic> sp = new Dictionary<int, dynamic>
{
{1, new {name="abc", age="1"}},
{2, new {name="def", age="2"}}
}
}
Controller:
public class TestController : Controller
{
Models.TestModels obj = new Models.TestModels();
}
How do I loop through the obj object and retrieve the values of the dictionary and print them in the view?
One way is to loop through the keys of the dictionary, which I recommend:
foreach(int key in sp.Keys)
dynamic value = sp[key];
Another way, is to loop through the dictionary as a sequence of pairs:
foreach(KeyValuePair<int, dynamic> pair in sp)
{
int key = pair.Key;
dynamic value = pair.Value;
}
I recommend the first approach, because you can have more control over the order of items retrieved if you decorate the Keys property with proper LINQ statements, e.g., sp.Keys.OrderBy(x => x) helps you retrieve the items in ascending order of the key. Note that Dictionary uses a hash table data structure internally, therefore if you use the second method the order of items is not easily predictable.
Update (01 Dec 2016): replaced vars with actual types to make the answer more clear.
It depends on what you are after in the Dictionary
Models.TestModels obj = new Models.TestModels();
foreach (var keyValuPair in obj.sp)
{
// KeyValuePair<int, dynamic>
}
foreach (var key in obj.sp.Keys)
{
// Int
}
foreach (var value in obj.sp.Values)
{
// dynamic
}
You can do it like this.
Models.TestModels obj = new Models.TestModels();
foreach (var item in obj.sp)
{
Console.Write(item.Key);
Console.Write(item.Value.name);
Console.Write(item.Value.age);
}
The problem you most likely have right now is that the collection is private. If you add public to the beginning of this line
Dictionary<int, dynamic> sp = new Dictionary<int, dynamic>
You should be able to access it from the function inside your controller.
Edit: Adding functional example of the full TestModels implementation.
Your TestModels class should look something like this.
public class TestModels
{
public Dictionary<int, dynamic> sp = new Dictionary<int, dynamic>();
public TestModels()
{
sp.Add(0, new {name="Test One", age=5});
sp.Add(1, new {name="Test Two", age=7});
}
}
You probably want to read up on the dynamic keyword as well.
public class TestModels
{
public Dictionary<int, dynamic> sp = new Dictionary<int, dynamic>();
public TestModels()
{
sp.Add(0, new {name="Test One", age=5});
sp.Add(1, new {name="Test Two", age=7});
}
}

C#, Can I move dictionary initial code out from the constructor?

Here is my code right now. But I would like to move those "Add" out from the constructor. Can we initialize Dictionary when we new it? or you have another better idea. Basically I want to define few characters which are used in many places.
public class User
{
public enum actionEnum
{
In,
Out,
Fail
}
public static Dictionary<actionEnum, String> loginAction = new Dictionary<actionEnum, string>();
public User()
{
loginAction.Add(actionEnum.In, "I");
loginAction.Add(actionEnum.Out, "O");
loginAction.Add(actionEnum.Fail, "F");
}
.....
}
You can use C# 3's collection initializer syntax:
public static Dictionary<actionEnum, String> loginAction = new Dictionary<actionEnum, string> {
{ actionEnum.In, "I" },
{ actionEnum.Out, "O" },
{ actionEnum.Fail, "F" }
};
Note, by the way, that the dictionary is mutable; any code can add or remove values.

Categories