首先,请原谅我的问题相当有趣的名字。我不是母语人士,我花了10分钟时间用这几个字来表达我的想法。
我要做的是在C#中创建一个字典,允许值为int
,string
或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
我的最终目标是为其他开发者提供一个库。此功能应使他们能够在运行时定义“变量”并为其提供类型。
编辑:// Firefox'关于:配置页面有一些非常接近我想要实现的东西
答案 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)
我建议:
这样您可以将词典限制为三种指定类型
答案 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?
一个想法是设计一个容器类,它可以容纳string
,int
或bool
中的一个。
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