5

我有一个如下的扩展方法:

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");

4

4 回答 4

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也不能解决您的问题

于 2010-04-06T12:59:16.467 回答
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 是什么,你必须在参数中包含 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));
于 2010-04-06T13:58:49.390 回答
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 

可能不想这样做,要么干草哼。

于 2010-04-06T14:34:05.100 回答
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,您不需要指定键和值的类型,但是由于字典从这里继承,因此无论您的字典是如何创建的,该函数都会保留。您甚至可以只使用对象而不是字符串作为键。

于 2017-05-09T08:27:13.183 回答