Related
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"];
I want to set up a lookup table like so:
Key Value
----- ------------------
Cat Lion, Tiger, Cheetah
Fish Dolphin, Whale
Dog . Pitbull, Doberman
An input of "Lion" would return the key "Cat"
I have set up 3 possible ways to initialize the data:
A Dictionary:
var map = new Dictionary<string,string>
{
["Dolphin"] = "Fish",
["Lion"] = "Cat",
//....
};
A HashSet:
var data = new Dictionary<string, HashSet<string>>
{
{"cat", new HashSet<string> {"Lion", "Tiger", "Cheetah"}},
{"fish", new HashSet<string> {"Dolphin", "Whale"}},
{"Dog", new HashSet<string> {"Pitbull", "Doberman"}}
};
A tuple:
var data = new List<Tuple<string, List<string>>>
{
Tuple.Create<string,List<string>> ("Cat", new List<string> { "Cheetah", "Lion" }),
Tuple.Create<string,List<string>> ("Dog", new List<string> { "Doberman", "Pitbull" }),
Tuple.Create<string,List<string>> ("Fish", new List<string> { "Dolphin", "Whale" }),
};
Given an animal, I want to return its type.
I know for the dictionary I can call the ContainsKey method.
Is there something similar for the other two options?
The data set isn't that big, (~15 keys that have 10 or so values), so I'm also wondering if one option would be better than the other in terms of performance.
I am suggesting a bit different approach.
public abstract class Animal
{
public string Type { get; }
public string Name { get; }
protected Animal(string type, string name)
{
Type = type;
Name = name;
}
}
public class Cat : Animal
{
public Cat(string name) : base("Cat", name)
{
}
}
public class Fish : Animal
{
public Fish(string name) : base("Fish", name)
{
}
}
public static class Program
{
public static void Main(string[] args)
{
List<Animal> list = new List<Animal>();
list.Add(new Cat("Cheetah"));
list.Add(new Fish("Dolphin"));
var cheetahType = list.FirstOrDefault(animal => animal.Name == "Cheetah")?.Type;
var doplhinType = list.FirstOrDefault(animal => animal.Name == "Dolphin")?.Type;
}
}
If you don't actually need that much, you can make Animal nonabstract and define enum instead of string Type and remove derived children.
Use the Dictionary<string, string> option.
var animalToType = new Dictionary<string,string>
{
["Dolphin"] = "Fish",
["Lion"] = "Cat",
//....
};
var lionType = animalToType["Lion"];
The other options are not going to be as simple. They will all involve loops, whether directly or hidden by Linq calls.
Personally, this architecture is a bit tricky... I mean, normally the lookup is based on keys, not on values, but I understand that sometimes you need to reverse the common logics and retrieve what you need within a data structure that is adequate in many other situations, except that one!
Anyway, if I was given the choice I would go for the HashSet approach, since it can grant a uniqueness of its values and also an immediate aggregation of the subtypes. But you can eventually run a benchmark and find out the fastest lookup solution in a few minutes.
Using the aforementioned approach (the HashSet one I mean), you can retrieve your type as follows:
String animalType = data.Where(kvp => kvp.Value.Contains("Dolphin")).Select(p => p.Key).FirstOrDefault();
// Animal type found: Fish!
if (animalType != null)
Console.WriteLine("Animal type found: " + animalType + "!");
else
Console.WriteLine("No animal type found!");
I hope I can explain my problem in a way that it's clear for everyone.
We need your suggestions on this.
We have an Enum Type which has more than 15 constants defined.
We receive a report from a web service and translate its one column into this Enum type.
And based on what we receive from that web service, we run specific functions using
Dictionary
Why am I asking for ideas?
Let's say 3 of these Enum contants meet specific functions in our Dictionary but the rest use the same function. So, is there a way to add them into our Dictionary in a better way rather than adding them one by one? I also want to keep this structure because when it's time, we might have specific functions in the future for the ones that I described as "the rest".
To be more clear here's an example what we're trying to do:
Enum:
public enum Reason{
ReasonA,
ReasonB,
ReasonC,
ReasonD,
ReasonE,
ReasonF,
ReasonG,
ReasonH,
ReasonI,
ReasonJ,
ReasonK
}
Defining our Dictionary:
public Dictionary<Reason, Action<CustomClassObj, string>> ReasonHandlers = new Dictionary<Reason, Action<CustomClassObj, string>>{
{ Reason.ReasonA, HandleReasonA },
{ Reason.ReasonB, HandleReasonB },
{ Reason.ReasonC, HandleReasonC },
{ Reason.ReasonD, HandleReasonGeneral },
{ Reason.ReasonE, HandleReasonGeneral },
{ Reason.ReasonF, HandleReasonGeneral },
{ Reason.ReasonG, HandleReasonGeneral },
{ Reason.ReasonH, HandleReasonGeneral },
{ Reason.ReasonI, HandleReasonGeneral },
{ Reason.ReasonJ, HandleReasonGeneral },
{ Reason.ReasonK, HandleReasonGeneral }
};
So basically what I'm asking is, is there a way to add Reason, Function pair more intelligently? Because as you can see after ReasonC, all other reasons use the same function.
Thank you for your suggestions.
You could try something like this, only put the custom Reason handler in the dictionary and then fallback to the General one.
public Dictionary<Reason, Action<CustomClassObj, string>> ReasonHandlers = new Dictionary<Reason, Action<CustomClassObj, string>>{
{ Reason.ReasonA, HandleReasonA },
{ Reason.ReasonB, HandleReasonB },
{ Reason.ReasonC, HandleReasonC }};
public Action<CustomClassObj, string> ReasonHandlerLookup (Reason reason) {
Action<CustomClassObj, string> result = null;
ReasonHandlers.TryGetValue(reason, out result);
return result ?? HandleReasonGeneral;
}
I am using below code :
var list = new Collection<ArrayList>
{
new ArrayList
{
1,
"Test1"
},
new ArrayList
{
2,
"Test2"
},
};
In the above code I want to avoid the ArrayList and use the Generics. Is it possible in the above code?
Edit:
Above I have used only two values in one arraylist object, I may have multiple items of int's and string's in it.
You can't mix types in a generic list (unless the generic type is object, but that equates to ArrayList and is just a perversion of generics).
But you can create a class that contains a string and int and use that as the generic parameter for a generic list.
public class MyClass
{
public MyString string { get; set; }
public MyInt int { get; set; }
}
var list = new Collection<MyClass>
{
new MyClass { MyInt = 1, MyString = "Test1" },
new MyClass { MyInt = 2, MyString = "Test2" }
}
Another alternative, if using .NET 4.0 is to use a Tuple, though I would rather have a strongly typed class.
(untested code):
var list = new Collection<Tuple<int,string>>
{
Tuple.Create(1, "Test1"),
Tuple.Create(2, "Test2")
}
No.
The whole point of generics is that you can't put an int and a string in the same collection.
Instead, you should create your own class with int and string properties, then create a generic collection of that class.
Not really, the fact that you have different types makes using a generic pointless.
You could use List<object> instead of ArrayList but there's really no point. Instead you could create a custom class to hold the 2 values and use that in a generic type.
John
Maybe you need Dictionary?
var list = new Dictionary<int, string>
{
{ 1, "Test1" },
{ 2, "Test2" }
};
var list = new List < Dictionary<int, string>> ();
then you can populate it was data as you need.
I'm not sure what you are actually trying to achieve, but it seems to me you are trying to mimic the behavior of a dictionary or map, that can map two different values to each other. These values could be of any type you want.
Something like this:
Dictionary<int, string> d = new Dictionary<int, string>();
d.Add(1, "Test1");
d.Add(2, "Test2");
and you can handle your data as simple as:
string t1 = d[1]; //will hold "Test1"
string t2 = d[2]; //will hold "Test2"
Do you want something like this?
In C#, is there an inline shortcut to instantiate a List<T> with only one item.
I'm currently doing:
new List<string>( new string[] { "title" } ))
Having this code everywhere reduces readability. I've thought of using a utility method like this:
public static List<T> SingleItemList<T>( T value )
{
return (new List<T>( new T[] { value } ));
}
So I could do:
SingleItemList("title");
Is there a shorter / cleaner way?
Thanks.
Simply use this:
List<string> list = new List<string>() { "single value" };
You can even omit the () braces:
List<string> list = new List<string> { "single value" };
Update: of course this also works for more than one entry:
List<string> list = new List<string> { "value1", "value2", ... };
var list = new List<string>(1) { "hello" };
Very similar to what others have posted, except that it makes sure to only allocate space for the single item initially.
Of course, if you know you'll be adding a bunch of stuff later it may not be a good idea, but still worth mentioning once.
Michael's idea of using extension methods leads to something even simpler:
public static List<T> InList<T>(this T item)
{
return new List<T> { item };
}
So you could do this:
List<string> foo = "Hello".InList();
I'm not sure whether I like it or not, mind you...
A different answer to my earlier one, based on exposure to the Google Java Collections:
public static class Lists
{
public static List<T> Of<T>(T item)
{
return new List<T> { item };
}
}
Then:
List<string> x = Lists.Of("Hello");
I advise checking out the GJC - it's got lots of interesting stuff in. (Personally I'd ignore the "alpha" tag - it's only the open source version which is "alpha" and it's based on a very stable and heavily used internal API.)
new[] { "item" }.ToList();
It's shorter than
new List<string> { "item" };
and you don't have to specify the type.
Use an extension method with method chaining.
public static List<T> WithItems(this List<T> list, params T[] items)
{
list.AddRange(items);
return list;
}
This would let you do this:
List<string> strings = new List<string>().WithItems("Yes");
or
List<string> strings = new List<string>().WithItems("Yes", "No", "Maybe So");
Update
You can now use list initializers:
var strings = new List<string> { "This", "That", "The Other" };
See http://msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx
Yet another way, found on "C#/.Net Little wonders" (unfortunately, the site doesn't exist anymore):
Enumerable.Repeat("value",1).ToList()
For a single item enumerable in java it would be Collections.singleton("string");
In c# this is going to be more efficient than a new List:
public class SingleEnumerator<T> : IEnumerable<T>
{
private readonly T m_Value;
public SingleEnumerator(T value)
{
m_Value = value;
}
public IEnumerator<T> GetEnumerator()
{
yield return m_Value;
}
IEnumerator IEnumerable.GetEnumerator()
{
yield return m_Value;
}
}
but is there a simpler way using the framework?
I've got this little function:
public static class CoreUtil
{
public static IEnumerable<T> ToEnumerable<T>(params T[] items)
{
return items;
}
}
Since it doesn't prescribe a concrete return type this is so generic that I use it all over the place. Your code would look like
CoreUtil.ToEnumerable("title").ToList();
But of course it also allows
CoreUtil.ToEnumerable("title1", "title2", "title3").ToArray();
I often use it in when I have to append/prepend one item to the output of a LINQ statement. For instance to add a blank item to a selection list:
CoreUtil.ToEnumerable("").Concat(context.TrialTypes.Select(t => t.Name))
Saves a few ToList() and Add statements.
(Late answer, but I stumbled upon this oldie and thought this could be helpful)
Try var
var s = new List<string> { "a", "bk", "ca", "d" };
You can also do
new List<string>() { "string here" };
I would just do
var list = new List<string> { "hello" };
Inspired by the other answers (and so I can pick it up whenever I need it!), but with naming/style aligned with F# (which has a standard singleton function per data structure*):
namespace System.Collections.Generic
{
public static class List
{
public static List<T> Singleton<T>(T value) => new List<T>(1) { value };
}
}
* except for ResizeArray itself of course, hence this question :)
In practice I actually name it Create to align with other helpers I define such as Tuple.Create, Lazy.Create[2], LazyTask.Create etc:
namespace System.Collections.Generic
{
public static class List
{
public static List<T> Create<T>(T value) => new List<T>(1) { value };
}
}
[2]
namespace System
{
public static class Lazy
{
public static Lazy<T> Create<T>(Func<T> factory) => new Lazy<T>(factory);
}
}
The declarations make it so easy now to do in C# 10.0 that I don't think theres a need for any helper. Just add the new(){} around any value you want to cast to a list.
List<string> values = new() { "single value" };
If someone landed on this page and trying to add object instead of string, then this worked for me.
new List<myObj> { new myObj{propertName=propstryValue }
, new myObj{propertName=propstryValue }, new myObj{propertName=propstryValue }
};
You need to create an inheritor from the List<> class
public class SingletonList<T> : List<T>
{
public SingletonList(T element) : base(1)
{
this.Add(element);
}
}
and you can use it instead of the base List<> class
var singletonList = new SingletonList<string>("Hello World!");