字典数量有限

时间:2013-03-28 17:35:53

标签: c#

首先,请原谅我的问题相当有趣的名字。我不是母语人士,我花了10分钟时间用这几个字来表达我的想法。

我要做的是在C#中创建一个字典,允许值为intstringbool。我首先想到的是使用泛型,但据我所知,我只能将一种类型定义为可能的值类型,而不是“成为其中之一”。使用object也是可能的,但拳击似乎是一个性能杀手。

有没有办法做到这一点?

以下是我想到的一个例子:

Dictionary<string, (string, int, bool)> foo = new Dictionary<string, (string, int, bool)>();
foo.Add("key1", "Hello, World!"); //Correct - Value is a string
foo.Add("key2", 37); //Correct - Value is an int
foo.Add("key3", true); //Correct - Value is a boolean
foo.Add("key4", new Foobar()); //Compiler error - Value is a Foobar

我的最终目标是为其他开发者提供一个库。此功能应使他们能够在运行时定义“变量”并为其提供类型。

编辑:// Firefox'关于:配置页面有一些非常接近我想要实现的东西

4 个答案:

答案 0 :(得分:6)

为什么不创建一个实现IDictionary的新类,并使用Dictionary作为私有变量。

然后,在add方法中,您可以提供自己的逻辑并相应地失败

示例代码

public class MyDic : IDictionary<object, object>
{
    private Dictionary<object, object> privateDic= new Dictionary<object,object>();


    public void Add(object key, object value)
    {
        if (value.GetType() == typeof(string))
            throw new ArgumentException();
        privateDic.Add(key, value);
    }
    //Rest of the interface follows
}

答案 1 :(得分:0)

我建议:

  1. 为字典值创建基本类型,例如MyDictionaryBaseType
  2. 为您拥有的每种字典值类型扩展此基本类型,例如StringDictionryType:MyDictionaryBaseType,IntegerDictionryType:MyDictionaryBaseType ... etc。
  3. 使用MyDictionaryBaseType创建通用字典类型,并限制类型以扩展此基本类型。
  4. 这样您可以将词典限制为三种指定类型

答案 2 :(得分:0)

您可以将值放入包装类中,如下所示:

class Value
{
}

class TypedValue<T> : Value
{
  public T Val;
}

class IntValue : TypedValue<int>
{
}

class StringValue : TypedValue<string>
{
}

class BoolValue : TypedValue<bool>
{
}

Dictionary<string,Value> foo;

foo.Add("key1", new StringValue{Val="Hello World!"});

另一种可能性是使用Dictionary并对添加的正确或错误类型执行运行时检查。我不认为没有涉及拳击的解决方案。

答案 3 :(得分:0)

您想要实现的目标并非类型安全。例如,假设您有这样的字典:

var foo = new Dictionary<string, (string, int, bool)>();
var x = foo["key1"];
// What type is x? How could the compiler know?

一个想法是设计一个容器类,它可以容纳stringintbool中的一个。

public class StringIntBool {
   private bool _isSet;
   private bool _isString;
   public bool IsString {
       get { return _isString; }
   }
   // ...

   private string _innerString;
   public string InnerString {
       get {
           return _innerString;
       }
       set {
           if (_isSet) {
               throw new Exception("StringIntBool is already set");
           }
           _isSet = true;
           _isString = true;
           _innerString = value;
       }
   }

   // etc...
}

这非常难看,并没有带来很多好处。

作为替代方案,您实际上可以将所有三个值存储为object,然后使用像Functional C#这样的技术/库来执行模式匹配,就像许多函数式语言一样。

object x = "str";
int res = x.Match()
    .With<string>(s => s == "str" ? 10 : 20)
    .With<int>(i => i)
    .With<bool>(b => b ? 50 : 60)
    .Return<int>();

这种编程模式在某些功能语言中实际上很常见。例如,在SML中,您可以定义数据类型,然后根据需要对其进行模式匹配。

(* StringIntBool *)
datatype sib = SibString of string | SibInt of int | SibBool of bool

val x = (* some instance of sib *)
val y = case x of
    SibString s => if s = "hello" then 50 else -50
  | SibInt i => i
  | SibBool b => if b then 10 else 20