我有一个包含Dictionary的抽象基类。我希望继承的类能够使用方便的语法访问字典字段。目前我有很多这样的代码:
string temp;
int val;
if (this.Fields.TryGetValue("Key", out temp)) {
if (int.TryParse(temp, out val)) {
// do something with val...
}
}
显然我可以将它包装在实用程序函数中,但是我希望有一个很酷,方便的语法来访问字典字段,我可以简单地说:
int result = @Key;
有没有办法在C#(3.5)中做这样的事情?
答案 0 :(得分:4)
您可以在类中添加索引器,并将索引器的参数传递给字典。
class Foo
{
// Initialized elsewhere
Dictionary<String,String> Fields;
public Int32 this[String key]
{
String temp = null;
Int32 val = 0;
if (this.Fields.TryGetValue(key, out temp)) {
Int32.TryParse(temp, out val);
}
return val;
}
}
然后给出一个名为Foo
foo
的实例,您可以这样做:
Int32 value = foo["Key"];
答案 1 :(得分:0)
扩展方法怎么样?
public static int TryGetInt(this IDictionary dict, string key)
{
int val;
if (dict.Contains(key))
{
if (int.TryParse((string)dict[key], out val))
return val;
else
throw new Exception("Value is not a valid integer.");
}
throw new Exception("Key not found.");
}
答案 2 :(得分:-1)
越接近一个好的语法就是使用扩展方法:
public static class MyDictExtensionMethods
{
public static T Get<T>(this Dictionary<string, object> dict, string key)
where T: IConvertible
{
object tmp;
if (!dict.TryGetValue(key, out tmp))
return default(T);
try {
return (T) Convert.ChangeType(tmp, typeof(T));
} catch (Exception) {
return default(T);
}
}
}
用法:
int val = this.Fields.Get<int>("Key");
然后,您可以为特定类型创建其他重载(即:未实现IConvertible且需要特定转换的类型)。
答案 3 :(得分:-1)
假设它并不总是你想要的int
(如果是,那么为什么它不是Dictionary<string, int>
?) - 我觉得这样的事情起作用并且非常接近:
int i = @int["Key"];
string s = @string["Key"];
object o = @object["Key"];
这结合了以下事实:标识符可以以@
作为前缀(它通常是可选的,但如果您的标识符是reserved keyword,则需要它,如int或string),其默认索引参数来自{{ 3}}
它确实需要使用另一个类来获取索引 - 尽管如果你想使用parens而不是方括号作为键名,你可以改用方法:
int i = @value<int>("Key");
实施将类似于:
class DerivedClass : BaseClass {
void Main() {
int i = @int["Key"];
}
}
abstract class BaseClass {
private Dictionary<string, string> D { get; set; }
protected Indexer<int> @int = new Indexer<int>(s => int.Parse(s), this);
protected Indexer<string> @string = new Indexer<string>(s => s, this);
protected Indexer<object> @object = new Indexer<object>(s => (object)s, this);
protected class Indexer<T> {
public T this[string key] {
get { return this.Convert(this.BaseClass.D[key]); }
}
private T Convert(string value) { get; set; }
private BaseClass { get; set; }
public Indexer(Func<T, string> c, BaseClass b) {
this.Convert = c;
this.BaseClass = b;
}
}
}
或者,方法路线:
class DerivedClass : BaseClass {
void Main() {
int i = @value<int>("key");
}
}
abstract class BaseClass {
private Dictionary<string, string> D { get; set; }
protected T @value<T>(string key) {
string s = this.D[s];
return Convert.ChangeType(s, typeof(T));
}
}
阅读Andrew Hare's answer后 - 如果您未与@
绑定,则_
是合法标识符。将它与索引器结合起来就可以得到:
int i = _["key"];