从Dictionary获取值无需拆箱?

发布于 2024-09-28 12:51:30 字数 1268 浏览 6 评论 0原文

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

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;
    }
}

提前致谢!

理查德.

I was wondering if it's possible to run the following code but without the unboxing line:-

t.Value = (T)x;

Or maybe if there is another way to do this kind of operation?

Here is the full code:-

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;
    }
}

Thanks in advance!!

Richard.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

世界如花海般美丽 2024-10-05 12:51:31

一些评论:

  1. t.Value = (T)x; 强制

转换是必要的。这是因为 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 实例,该实例指示字典中不存在具有键 key 的对象。我认为这与大多数人的期望非常违反直觉。

此外,如果您不想在 dictionary 不包含与键 key 匹配的值时抛出,我认为您应该将您的方法重命名为 TryGetValue< /code>,接受 ValueWrapper 类型的 out 参数,并返回指示成功/失败的 bool

3.

针对您的评论,这是一种解决方案。

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;
        }
    }
}

用法:

var dict = new Dictionary<string, IValueWrapper>();
dict.Add("hello", 5);
ValueWrapper<int> value;
dict.TryGetWrappedValue("hello", out value);

您必须添加参数检查等。

A few comments:

  1. t.Value = (T)x;

The cast is necessary. This is because t.Value is of type T and x is of type object. The strongly-typed nature of C# requires that you tell the compiler "look, I know this might unsafe but can you just try to do it for me anyway, either by conversion or unboxing or whatever? Thanks!"

2.

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

return t;

What if x is an instance of a class that derives from T? Or if x is an instance of a class that implements an interface and T is that interface? Right now, you will return a instance of ValueWrapper<T> that indicates there was no object in the dictionary with the key key. I would argue this is very counterintuitive to what most people expect.

Additionally, if you're not going to throw up when dictionary does not contain a value matching the key key, I think you should rename your method to TryGetValue, accept a out parameter of type ValueWrapper<T>, and return a bool indicating success/failure.

3.

Responding to your comment, here's one solution.

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;
        }
    }
}

Usage:

var dict = new Dictionary<string, IValueWrapper>();
dict.Add("hello", 5);
ValueWrapper<int> value;
dict.TryGetWrappedValue("hello", out value);

You'll have to add parameter checking etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文