What is the most efficient way to create a constant (never changes at runtime) mapping of string
s to int
s?
I've tried using a const Dictionary, but that didn't work out.
I could implement a immutable wrapper with appropriate semantics, but that still doesn't seem totally right.
For those who have asked, I'm implementing IDataErrorInfo in a generated class and am looking for a way to make the columnName lookup into my array of descriptors.
I wasn't aware (typo when testing! d'oh!) that switch accepts strings, so that's what I'm gonna use. Thanks!
This question is related to
c#
.net
collections
dictionary
constants
enum Constants
{
Abc = 1,
Def = 2,
Ghi = 3
}
...
int i = (int)Enum.Parse(typeof(Constants), "Def");
This is the closest thing you can get to a "CONST Dictionary":
public static int GetValueByName(string name)
{
switch (name)
{
case "bob": return 1;
case "billy": return 2;
default: return -1;
}
}
The compiler will be smart enough to build the code as clean as possible.
Why not use namespaces or classes to nest your values? It may be imperfect, but it is very clean.
public static class ParentClass
{
// here is the "dictionary" class
public static class FooDictionary
{
public const string Key1 = "somevalue";
public const string Foobar = "fubar";
}
}
Now you can access .ParentClass.FooDictionary.Key1, etc.
There are precious few immutable collections in the current framework. I can think of one relatively pain-free option in .NET 3.5:
Use Enumerable.ToLookup()
- the Lookup<,>
class is immutable (but multi-valued on the rhs); you can do this from a Dictionary<,>
quite easily:
Dictionary<string, int> ids = new Dictionary<string, int> {
{"abc",1}, {"def",2}, {"ghi",3}
};
ILookup<string, int> lookup = ids.ToLookup(x => x.Key, x => x.Value);
int i = lookup["def"].Single();
This is the closest thing you can get to a "CONST Dictionary":
public static int GetValueByName(string name)
{
switch (name)
{
case "bob": return 1;
case "billy": return 2;
default: return -1;
}
}
The compiler will be smart enough to build the code as clean as possible.
Just another idea since I am binding to a winforms combobox:
public enum DateRange {
[Display(Name = "None")]
None = 0,
[Display(Name = "Today")]
Today = 1,
[Display(Name = "Tomorrow")]
Tomorrow = 2,
[Display(Name = "Yesterday")]
Yesterday = 3,
[Display(Name = "Last 7 Days")]
LastSeven = 4,
[Display(Name = "Custom")]
Custom = 99
};
int something = (int)DateRange.None;
To get the int value from the display name from:
public static class EnumHelper<T>
{
public static T GetValueFromName(string name)
{
var type = typeof(T);
if (!type.IsEnum) throw new InvalidOperationException();
foreach (var field in type.GetFields())
{
var attribute = Attribute.GetCustomAttribute(field,
typeof(DisplayAttribute)) as DisplayAttribute;
if (attribute != null)
{
if (attribute.Name == name)
{
return (T)field.GetValue(null);
}
}
else
{
if (field.Name == name)
return (T)field.GetValue(null);
}
}
throw new ArgumentOutOfRangeException("name");
}
}
usage:
var z = (int)EnumHelper<DateRange>.GetValueFromName("Last 7 Days");
There are precious few immutable collections in the current framework. I can think of one relatively pain-free option in .NET 3.5:
Use Enumerable.ToLookup()
- the Lookup<,>
class is immutable (but multi-valued on the rhs); you can do this from a Dictionary<,>
quite easily:
Dictionary<string, int> ids = new Dictionary<string, int> {
{"abc",1}, {"def",2}, {"ghi",3}
};
ILookup<string, int> lookup = ids.ToLookup(x => x.Key, x => x.Value);
int i = lookup["def"].Single();
Why not:
public class MyClass
{
private Dictionary<string, int> _myCollection = new Dictionary<string, int>() { { "A", 1 }, { "B", 2 }, { "C", 3 } };
public IEnumerable<KeyValuePair<string,int>> MyCollection
{
get { return _myCollection.AsEnumerable<KeyValuePair<string, int>>(); }
}
}
enum Constants
{
Abc = 1,
Def = 2,
Ghi = 3
}
...
int i = (int)Enum.Parse(typeof(Constants), "Def");
I am not sure why no one mentioned this but in C# for things that I cannot assign const, I use static read-only properties.
Example:
public static readonly Dictionary<string, string[]> NewDictionary = new Dictionary<string, string[]>()
{
{ "Reference1", Array1 },
{ "Reference2", Array2 },
{ "Reference3", Array3 },
{ "Reference4", Array4 },
{ "Reference5", Array5 }
};
I am not sure why no one mentioned this but in C# for things that I cannot assign const, I use static read-only properties.
Example:
public static readonly Dictionary<string, string[]> NewDictionary = new Dictionary<string, string[]>()
{
{ "Reference1", Array1 },
{ "Reference2", Array2 },
{ "Reference3", Array3 },
{ "Reference4", Array4 },
{ "Reference5", Array5 }
};
If using 4.5+ Framework I would use ReadOnlyDictionary (also ReadOnly Collection for lists) to do readonly mappings/constants. It's implemented in the following way.
static class SomeClass
{
static readonly ReadOnlyDictionary<string,int> SOME_MAPPING
= new ReadOnlyDictionary<string,int>(
new Dictionary<string,int>()
{
{ "One", 1 },
{ "Two", 2 }
}
)
}
There does not seem to be any standard immutable interface for dictionaries, so creating a wrapper seems like the only reasonable option, unfortunately.
Edit: Marc Gravell found the ILookup that I missed - that will allow you to at least avoid creating a new wrapper, although you still need to transform the Dictionary with .ToLookup().
If this is a need constrained to a specific scenario, you might be better off with a more business-logic-oriented interface:
interface IActiveUserCountProvider
{
int GetMaxForServer(string serverName);
}
There are precious few immutable collections in the current framework. I can think of one relatively pain-free option in .NET 3.5:
Use Enumerable.ToLookup()
- the Lookup<,>
class is immutable (but multi-valued on the rhs); you can do this from a Dictionary<,>
quite easily:
Dictionary<string, int> ids = new Dictionary<string, int> {
{"abc",1}, {"def",2}, {"ghi",3}
};
ILookup<string, int> lookup = ids.ToLookup(x => x.Key, x => x.Value);
int i = lookup["def"].Single();
enum Constants
{
Abc = 1,
Def = 2,
Ghi = 3
}
...
int i = (int)Enum.Parse(typeof(Constants), "Def");
If using 4.5+ Framework I would use ReadOnlyDictionary (also ReadOnly Collection for lists) to do readonly mappings/constants. It's implemented in the following way.
static class SomeClass
{
static readonly ReadOnlyDictionary<string,int> SOME_MAPPING
= new ReadOnlyDictionary<string,int>(
new Dictionary<string,int>()
{
{ "One", 1 },
{ "Two", 2 }
}
)
}
There does not seem to be any standard immutable interface for dictionaries, so creating a wrapper seems like the only reasonable option, unfortunately.
Edit: Marc Gravell found the ILookup that I missed - that will allow you to at least avoid creating a new wrapper, although you still need to transform the Dictionary with .ToLookup().
If this is a need constrained to a specific scenario, you might be better off with a more business-logic-oriented interface:
interface IActiveUserCountProvider
{
int GetMaxForServer(string serverName);
}
Why not:
public class MyClass
{
private Dictionary<string, int> _myCollection = new Dictionary<string, int>() { { "A", 1 }, { "B", 2 }, { "C", 3 } };
public IEnumerable<KeyValuePair<string,int>> MyCollection
{
get { return _myCollection.AsEnumerable<KeyValuePair<string, int>>(); }
}
}
Why not use namespaces or classes to nest your values? It may be imperfect, but it is very clean.
public static class ParentClass
{
// here is the "dictionary" class
public static class FooDictionary
{
public const string Key1 = "somevalue";
public const string Foobar = "fubar";
}
}
Now you can access .ParentClass.FooDictionary.Key1, etc.
This is the closest thing you can get to a "CONST Dictionary":
public static int GetValueByName(string name)
{
switch (name)
{
case "bob": return 1;
case "billy": return 2;
default: return -1;
}
}
The compiler will be smart enough to build the code as clean as possible.
There are precious few immutable collections in the current framework. I can think of one relatively pain-free option in .NET 3.5:
Use Enumerable.ToLookup()
- the Lookup<,>
class is immutable (but multi-valued on the rhs); you can do this from a Dictionary<,>
quite easily:
Dictionary<string, int> ids = new Dictionary<string, int> {
{"abc",1}, {"def",2}, {"ghi",3}
};
ILookup<string, int> lookup = ids.ToLookup(x => x.Key, x => x.Value);
int i = lookup["def"].Single();
enum Constants
{
Abc = 1,
Def = 2,
Ghi = 3
}
...
int i = (int)Enum.Parse(typeof(Constants), "Def");
Just another idea since I am binding to a winforms combobox:
public enum DateRange {
[Display(Name = "None")]
None = 0,
[Display(Name = "Today")]
Today = 1,
[Display(Name = "Tomorrow")]
Tomorrow = 2,
[Display(Name = "Yesterday")]
Yesterday = 3,
[Display(Name = "Last 7 Days")]
LastSeven = 4,
[Display(Name = "Custom")]
Custom = 99
};
int something = (int)DateRange.None;
To get the int value from the display name from:
public static class EnumHelper<T>
{
public static T GetValueFromName(string name)
{
var type = typeof(T);
if (!type.IsEnum) throw new InvalidOperationException();
foreach (var field in type.GetFields())
{
var attribute = Attribute.GetCustomAttribute(field,
typeof(DisplayAttribute)) as DisplayAttribute;
if (attribute != null)
{
if (attribute.Name == name)
{
return (T)field.GetValue(null);
}
}
else
{
if (field.Name == name)
return (T)field.GetValue(null);
}
}
throw new ArgumentOutOfRangeException("name");
}
}
usage:
var z = (int)EnumHelper<DateRange>.GetValueFromName("Last 7 Days");
This is the closest thing you can get to a "CONST Dictionary":
public static int GetValueByName(string name)
{
switch (name)
{
case "bob": return 1;
case "billy": return 2;
default: return -1;
}
}
The compiler will be smart enough to build the code as clean as possible.
There does not seem to be any standard immutable interface for dictionaries, so creating a wrapper seems like the only reasonable option, unfortunately.
Edit: Marc Gravell found the ILookup that I missed - that will allow you to at least avoid creating a new wrapper, although you still need to transform the Dictionary with .ToLookup().
If this is a need constrained to a specific scenario, you might be better off with a more business-logic-oriented interface:
interface IActiveUserCountProvider
{
int GetMaxForServer(string serverName);
}
Source: Stackoverflow.com