我有一个如下所示的扩展方法:
public static T GetValueAs<T, R>(this IDictionary<string, R> dictionary, string fieldName)
where T : R
{
R value;
if (!dictionary.TryGetValue(fieldName, out value))
return default(T);
return (T)value;
}
目前,我可以通过以下方式使用它:
var dictionary = new Dictionary<string, object>();
//...
var list = dictionary.GetValueAs<List<int>, object>("A"); // this may throw ClassCastException - this is expected behavior;
它工作得很好,但第二个类型参数真的很烦人。是否有可能在C#4.0中重写GetValueAs是这样一种方式,该方法仍然适用于不同类型的字符串键控字典,并且不需要在调用代码中指定第二个类型参数,即使用
var list = dictionary.GetValueAs<List<int>>("A");
或至少类似 var list = dictionary.GetValueAs<List<int>, ?>("A");
而不是 var list = dictionary.GetValueAs<List<int>, object>("A");
答案 0 :(得分:1)
只要您只在对象的词典中使用它,就可以将T约束为引用类型以使转换有效:
public static T GetValueAs<T>(this IDictionary<string, object> dictionary, string fieldName)
where T : class {
object value;
if (!dictionary.TryGetValue(fieldName, out value))
return default(T);
return (T)value;
}
但那可能不是你想要的。请注意C#版本4 doesn't solve your problem。
答案 1 :(得分:0)
怎么样?
public static void GetValueAs<T, R>(this IDictionary<string, R> dictionary, string fieldName, out T value)
where T : R
{
value = default(T);
dictionary.TryGetValue(fieldName, out value)
}
然后你可以做类似
的事情List<int> list;
dictionary.GetValueAs("fieldName", out list);
基本上要知道你需要在参数中使用T类型的东西。
修改强>
也许更好的方法是
public static T GetValueAs<T, R>(
this IDictionary<string, R> dictionary,
string fieldName,
T defaultValue)
where T : R
{
R value = default(R);
return dictionary.TryGetValue(fieldName, out value) ?
(T)value : defaultValue;
}
然后你可以使用var和chain,这使你能够控制默认值。
var x = dict.GetValueAs("A", new Dictionary<string,int>).GetValueAs("B", default(int));
答案 2 :(得分:0)
也许你可以为这种行为制作自己的字典类:
public class CastableDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
public TOut GetValueAs<TOut>(TKey key) where TOut : TValue
{
TValue result;
if (this.TryGetValue(key, out result))
{
return (TOut)result;
}
return default(TOut);
}
}
var d = new CastableDictionary<string, object>();
d.Add("A", 1);
d.Add("B", new List<int>() { 1, 2, 3});
var a = d.GetValueAs<int>("A"); // = 1
var b = d.GetValueAs<List<int>>("B"); //= 1, 2, 3
可能不想干草哼。
答案 3 :(得分:0)
我错过了什么,当然这就是你想要的吗?也许你需要更好的转换,但对于一般演员,这应该做:
public static T getValueAs<T>(this IDictionary dict, string key)
{
try
{
return (T)dict[key];
} catch
{
return default(T);
}
}
用法只是
MyDictionary.getValueAs<Int32>("hello");
使用IDictionary,您不需要指定键和值的类型,但是当字典继承此函数时,无论您的字典是如何创建的,函数都会保留。您甚至可以使用对象而不是字符串作为密钥。