从Dictionary <string,object =“”>获取值而不取消装箱?</string,>

时间:2010-10-20 22:23:13

标签: c# generics casting boxing

我想知道是否可以运行以下代码但没有取消装箱行: -

t.Value = (T)x;

或者,如果还有其他方法可以进行此类操作?

以下是完整代码: -

public class ValueWrapper<T>
{
    public T Value { get; set; }
    public bool HasValue { get; set; }

    public ValueWrapper()
    {
        HasValue = false;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Dictionary<string, object> myDictionary = new Dictionary<string, object>();

        myDictionary.Add("key1", 6);
        myDictionary.Add("key2", "a string");

        var x2 = GetValue<int>(myDictionary, "key1");
        if (x2.HasValue)
            Console.WriteLine("'{0}' = {1}", "key1", x2.Value);
        else
            Console.WriteLine("No value found");

        Console.ReadLine();
    }

    static ValueWrapper<T> GetValue<T>(IDictionary<string, object> dictionary, string key)
    {
        ValueWrapper<T> t = new ValueWrapper<T>();

        object x = null;
        if (dictionary.TryGetValue(key, out x))
        {
            if (x.GetType() == typeof(T))
            {
                t.Value = (T)x;
                t.HasValue = true;
            }
        }

        return t;
    }
}

提前致谢!!

理查德。

1 个答案:

答案 0 :(得分:6)

一些评论:

  1. t.Value = (T)x;
  2. 演员是必要的。这是因为t.Value的类型为T,而x的类型为object。 C#的强类型性质要求你告诉编译器“看,我知道这可能不安全,但你可以尝试为我做这件事,无论是通过转换或拆箱还是其他什么?谢谢!”

    2

    object x = null;
    if (dictionary.TryGetValue(key, out x)) {
        if (x.GetType() == typeof(T)) {
            t.Value = (T)x;
            t.HasValue = true;
        }
    }
    
    return t;
    

    如果x是从T派生的类的实例,该怎么办?或者,如果x是实现接口的类的实例,那么T是该接口?现在,您将返回ValueWrapper<T>的实例,该实例指示字典中没有带有键key的对象。我认为这与大多数人的期望非常违反直觉。

    此外,如果dictionary不包含与键key匹配的值时您不会呕吐,我认为您应该将方法重命名为TryGetValue,接受类型为out的{​​{1}}参数,并返回表示成功/失败的ValueWrapper<T>

    3

    回复您的评论,这是一个解决方案。

    bool

    用法:

    public interface IValueWrapper {
        object Value { get; set; }
        bool HasValue { get; set; }
    }
    
    public class ValueWrapper<T> : IValueWrapper {
        public T Value { get; set; }
        object IValueWrapper.Value { 
            get { return Value; }
            set { this.Value = (T)value; }
        }
        public bool HasValue { get; set; }
    
        public ValueWrapper() {
            this.HasValue = false;
        }
    
        public ValueWrapper(T value) {
            this.Value = value;
            this.HasValue = value != null;
        }
    }
    
    public static class DictionaryExtensions {
        public static void Add<T>(
            this IDictionary<string, IValueWrapper> dictionary,
            string key,
            T value
        ) {
            ValueWrapper<T> valueWrapper = new ValueWrapper<T>(value);
            dictionary.Add(key, valueWrapper);
        }
    
        public static bool TryGetWrappedValue<T>(
            IDictionary<string, IValueWrapper> dictionary,
            string key,
            out ValueWrapper<T> value
        ) {
            IValueWrapper valueWrapper;
            if (dictionary.TryGetValue(key, out valueWrapper)) {
                value = (ValueWrapper<T>)valueWrapper;
                return true;
            }
            else {
                value = null;
                return false;
            }
        }
    }
    

    您必须添加参数检查等。