限制C#字典中的值类型:

时间:2017-02-27 20:51:02

标签: c# dictionary types

我想要的是Dictionary<string, T>,其中T仅限于少数类型中的一种。

如果C#具有Typescript联合类型,它看起来像Dictionary<string, bool | string | int | List<string> | List<int>>

我所做的是围绕Dictionary编写一个包装类,它对于各个受支持的类型有一堆Add()的重载,并且有GetBool()GetString()等方法用于检索。见http://pastebin.com/av7nE5az

这是有效的,但它的冗长,丑陋和繁琐,我认为必须有更好的方法。有人有一个吗?

编辑:有关我为什么要这样做的一些问题。基本上我想要Dictionary<string, object>,实例可能包含多种类型的值,但我希望以约束的方式(在游戏中)使用它,因此可能的值类型列表是有限的。我可以通过使用Dictionary<string, object>并转换每个检索来获得,但我认为如果我可以在数据结构本身中构建更多类型感知会更好。

1 个答案:

答案 0 :(得分:3)

如果您的目标是使用更简单的代码和编译时类型检查,则可以使用此方法,但它可能会略微影响性能。

  1. 将字典定义为Dictionary<string, MyEntry>

  2. 编写一个能够存储所有感兴趣的数据类型的新类MyEntry

  3. MyEntry和感兴趣的数据类型之间写implicit conversion operators。它可能看起来像这个示例,它可以处理boolint(您可以根据需要为其他数据类型扩展它):

    class MyEntry
    {
        private Type _type = typeof(object);
        private bool _boolValue = false;
        private int _intValue = 0;
    
        public MyEntry(bool b)
        {
            _type = typeof(bool);
            _boolValue = b;
        }
    
        public MyEntry(int i)
        {
            _type = typeof(int);
            _intValue = i;
        }
    
        public static implicit operator bool(MyEntry e)
        {
            if (e._type != typeof(bool)) throw new InvalidCastException();
            return e._boolValue;
        }
        public static implicit operator MyEntry(bool b)
        {
            return new MyEntry(b);
        }
        public static implicit operator int(MyEntry e)
        {
            if (e._type != typeof(int)) throw new InvalidCastException();
            return e._intValue;
        }
        public static implicit operator MyEntry(int i)
        {
            return new MyEntry(i);
        }
    }
    
  4. 然后,您可以编写简明的代码,以便在没有显式强制转换的情况下从此字典中读取和写入。您可以通过限制为MyEntry实现的隐式转换来控制允许的类型。

    var d = new Dictionary<string, MyEntry>();
    d.Add("IntegerOne", 1);
    d.Add("BooleanTrue", true);
    d.Add("FloatThree", 3.0f);  //Will not compile
    
    bool b = d["BooleanTrue"];
    int i = d["IntegerOne"];
    float f = d["FloatThree"]; //Will not compile
    
    Console.WriteLine(string.Format("BooleanTrue = '{0}'", b));
    Console.WriteLine(string.Format("IntegerOne = '{0}'", i));