6

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

我想要做的是在 C# 中创建一个字典,允许值是 a int、 astring或 a bool。我首先想到的是使用泛型,但据我所知,我只能将一种类型定义为可能的值类型,而不是“成为其中之一”。使用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

我的最终目标是为其他开发人员提供一个库。这个特性应该使他们能够在运行时定义“变量”并给他们一个类型。

Edit://Firefox' about:config 页面的内容非常接近我想要实现的目标

4

4 回答 4

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
}
于 2013-03-28T17:54:43.587 回答
0

我建议:

  1. 为您的字典值创建一个基本类型,例如 MyDictionaryBaseType
  2. 为您拥有的每个字典值类型扩展此基本类型,例如 StringDictionryType:MyDictionaryBaseType、IntegerDictionryType:MyDictionaryBaseType...等。
  3. 使用 MyDictionaryBaseType 创建泛型字典类型并限制类型以扩展此基本类型。

通过这种方式,您可以将字典限制为三种指定类型

于 2013-03-28T17:42:30.573 回答
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 并对添加的正确或错误类型进行运行时检查。我认为没有涉及拳击的解决方案。

于 2013-03-28T17:59:59.190 回答
0

您要完成的工作不是类型安全的。例如,假设您有这样一本字典:

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

一个想法是设计一个容器类,它可以容纳string,intbool.

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

这很丑陋,并没有真正带来很多好处。

作为替代方案,您实际上可以将所有三个值都存储为objects,然后使用诸如函数式 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
于 2013-03-28T18:01:08.783 回答