在 C# 中创建一个常量字典
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/268084/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Creating a constant Dictionary in C#
提问by David Schmitt
What is the most efficient way to create a constant(never changes at runtime) mapping of string
s to int
s?
创建s 到s的常量(在运行时永远不会更改)映射的最有效方法是什么?string
int
I've tried using a const Dictionary, but that didn't work out.
我试过使用const Dictionary,但没有成功。
I could implement a immutable wrapperwith appropriate semantics, but that still doesn't seem totally right.
我可以用适当的语义实现一个不可变的包装器,但这似乎仍然不完全正确。
For those who have asked, I'm implementing IDataErrorInfoin a generated class and am looking for a way to make the columnName lookup into my array of descriptors.
对于那些问过的人,我正在生成的类中实现IDataErrorInfo并且正在寻找一种方法来使 columnName 查找到我的描述符数组中。
I wasn't aware (typo when testing! d'oh!) that switch accepts strings, so that's what I'm gonna use. Thanks!
我不知道(测试时打错了!d'oh!) switch 接受字符串,所以这就是我要使用的。谢谢!
采纳答案by Tamas Czinege
Creating a truly compile-time generated constant dictionary in C# is not really a straightforward task. Actually, none of the answers here really achieve that.
在 C# 中创建真正的编译时生成的常量字典并不是一项简单的任务。实际上,这里的答案都没有真正做到这一点。
There is one solution though which meets your requirements, although not necessarily a nice one; remember that according to the C# specification, switch-case tables are compiled to constant hash jump tables. That is, they are constant dictionaries, not a series of if-else statements. So consider a switch-case statement like this:
虽然有一种解决方案可以满足您的要求,但不一定是好的解决方案;请记住,根据 C# 规范,switch-case 表被编译为常量哈希跳转表。也就是说,它们是常量字典,而不是一系列 if-else 语句。所以考虑一个像这样的 switch-case 语句:
switch (myString)
{
case "cat": return 0;
case "dog": return 1;
case "elephant": return 3;
}
This is exactly what you want. And yes, I know, it's ugly.
这正是您想要的。是的,我知道,这很丑陋。
回答by Sander
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().
编辑:Marc Gravell 找到了我错过的 ILookup - 这将允许您至少避免创建新的包装器,尽管您仍然需要使用 .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);
}
回答by Marc Gravell
There are precious few immutable collections in the current framework. I can think of one relatively pain-free option in .NET 3.5:
当前框架中几乎没有不可变的集合。我可以想到 .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:
使用Enumerable.ToLookup()
-Lookup<,>
类是不可变的(但在 rhs 上是多值的);你可以Dictionary<,>
很容易地做到这一点:
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();
回答by Richard Poole
enum Constants
{
Abc = 1,
Def = 2,
Ghi = 3
}
...
int i = (int)Enum.Parse(typeof(Constants), "Def");
回答by Timothy Khouri
This is the closest thing you can get to a "CONST Dictionary":
这是最接近“CONST 字典”的内容:
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.
编译器将足够聪明以构建尽可能干净的代码。
回答by Timothy Khouri
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>>(); }
}
}
回答by Joshua
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.
现在您可以访问 .ParentClass.FooDictionary.Key1 等。
回答by Kram
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.
如果使用 4.5+ 框架,我将使用 ReadOnlyDictionary(也是列表的只读集合)来做只读映射/常量。它通过以下方式实现。
static class SomeClass
{
static readonly ReadOnlyDictionary<string,int> SOME_MAPPING
= new ReadOnlyDictionary<string,int>(
new Dictionary<string,int>()
{
{ "One", 1 },
{ "Two", 2 }
}
)
}
回答by Suleman
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.
我不确定为什么没有人提到这一点,但在 C# 中,对于无法分配 const 的内容,我使用静态只读属性。
Example:
例子:
public static readonly Dictionary<string, string[]> NewDictionary = new Dictionary<string, string[]>()
{
{ "Reference1", Array1 },
{ "Reference2", Array2 },
{ "Reference3", Array3 },
{ "Reference4", Array4 },
{ "Reference5", Array5 }
};
回答by Gina Marano
Just another idea since I am binding to a winforms combobox:
这是另一个想法,因为我绑定到了一个 winforms 组合框:
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:
为了从显示名称的int值从:
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");