C# 从字典中获取值<;字符串,对象>;不拆箱?

C# 从字典中获取值<;字符串,对象>;不拆箱?,c#,generics,casting,boxing,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; } } c

我想知道是否可以运行以下代码,但不需要取消装箱行:-

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;
    }
}
public类ValueWrapper
{
公共T值{get;set;}
公共bool HasValue{get;set;}
公共价值包装器()
{
HasValue=false;
}
}
班级计划
{
静态void Main(字符串[]参数)
{
Dictionary myDictionary=新字典();
添加(“键1”,6);
添加(“键2”,“字符串”);
var x2=GetValue(myDictionary,“key1”);
if(x2.HasValue)
WriteLine(“{0}'={1}”,“key1”,x2.Value);
其他的
Console.WriteLine(“未找到值”);
Console.ReadLine();
}
静态值包装器GetValue(IDictionary字典,字符串键)
{
ValueWrapper t=新的ValueWrapper();
对象x=null;
if(dictionary.TryGetValue(键,out x))
{
if(x.GetType()==typeof(T))
{
t、 值=(t)x;
t、 HasValue=true;
}
}
返回t;
}
}
提前谢谢

Richard.

一些评论:

  • t.Value=(t)x
  • 演员阵容是必要的。这是因为
    t.Value
    属于
    t
    类型,
    x
    属于
    object
    类型。C#的强类型特性要求你告诉编译器“听着,我知道这可能不安全,但你能不能试着为我这样做,通过转换或取消打包或其他方式?谢谢!”

    二,

    如果
    x
    是从
    T
    派生的类的实例,该怎么办?或者如果
    x
    是实现接口的类的实例,而
    T
    是接口吗?现在,您将返回
    ValueWrapper
    的实例,该实例指示字典中没有键为
    key
    的对象。我认为这与大多数人的预期是背道而驰的

    此外,如果您不想在
    dictionary
    不包含与键
    key
    匹配的值时呕吐,我认为您应该将您的方法重命名为
    TryGetValue
    ,接受类型为
    ValueWrapper
    out
    参数,并返回指示成功/失败的
    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;
            }
        }
    }
    
    公共接口{
    对象值{get;set;}
    bool HasValue{get;set;}
    }
    公共类ValueWrapper:IValueWrapper{
    公共T值{get;set;}
    对象IValueWrapper.Value{
    获取{返回值;}
    设置{this.Value=(T)Value;}
    }
    公共bool HasValue{get;set;}
    公共价值包装器(){
    this.HasValue=false;
    }
    公共价值包装(T值){
    这个。值=值;
    this.HasValue=value!=null;
    }
    }
    公共静态类字典扩展{
    公共静态无效添加(
    这本词典,
    字符串键,
    T值
    ) {
    ValueWrapper ValueWrapper=新的ValueWrapper(值);
    dictionary.Add(key,valueWrapper);
    }
    公共静态bool tryGetTrappedValue(
    词典,
    字符串键,
    out ValueWrapper值
    ) {
    IValueWrapper-valueWrapper;
    if(dictionary.TryGetValue(key,out valueWrapper)){
    value=(ValueWrapper)ValueWrapper;
    返回true;
    }
    否则{
    值=空;
    返回false;
    }
    }
    }
    
    用法:

    var dict = new Dictionary<string, IValueWrapper>();
    dict.Add("hello", 5);
    ValueWrapper<int> value;
    dict.TryGetWrappedValue("hello", out value);
    
    var dict=newdictionary();
    dict.Add(“你好”,5);
    价值包装价值;
    dict.tryGetTrappedValue(“hello”,输出值);
    

    您必须添加参数检查等。

    否,如果您的
    对象
    是装箱值类型,则需要取消装箱。您希望避免取消绑定有什么原因吗?主要是为了性能,因为在我的项目中,此代码与其他内容一起使用。取消绑定将执行时间从~200ms增加到~1700ms。这仍然是可以接受的,为了我自己的利益,我只想知道是否有其他选择。这种性能的急剧下降极不可能是由于拆箱造成的。使用探查器来确定真正的瓶颈是什么。感谢您这么快的回复,我想知道是否有一种方法可以使对象不是字典中的V,但可能有其他方法来防止取消绑定,因为它可能非常慢。另外,我已经改变了我的方法来引用ValueWrapper并返回true/false,老实说,我没有想到这一点。它应该是
    out
    ,而不是
    ref
    @Richard Adnams:我怀疑这会导致性能问题,但你只能知道是否需要配置文件。但是,请参阅我的编辑,了解解决您试图解决的问题的一种方法。谢谢您,杰森,您帮了大忙。。现在去喝杯咖啡,消化一下这个:)!
    var dict = new Dictionary<string, IValueWrapper>();
    dict.Add("hello", 5);
    ValueWrapper<int> value;
    dict.TryGetWrappedValue("hello", out value);