需要一个类型安全的商品袋,这些商品都实现了通用界面。
希望做的事情如下:
var stringItem = new IItem<string>();
var numberItem = new IItem<int>();
var items = new List<IItem<T>>(); //T of course doesn't accomplish what I want
items.Add(stringItem);
items.Add(numberItem);
类似的东西:
interface IItem
{
object Value { get; set; }
}
//Update: 2009-03-19 03:08 PM MST
//Added the following interface for clarity of my question
interface IItem<T> : IItem
{
new T Value { get; set; }
}
然后,我可以:
var items = new List<IItem>();
但是,我的包里丢失了安全性。所以,我想到了Dictionary
:
var dict = new Dictionary<Type, List<IItem<T>>>(); //T is wrong again
dict.Add(typeof(string), new List<IItem<string>>); //that sure looks nice
答案 0 :(得分:5)
我认为你不能逃避IItem<int>
和IItem<string>
不同的事实;通常的方法是基础接口:
interface IItem {
object Value {get;}
}
interface IItem<T> : IItem {
new T Value {get;}
}
这样,您针对IItem
进行编码,但实际的实例(通常为某些IItem<T>
实现T
)在内部是强类型的。
答案 1 :(得分:1)
查看PolyDictionary实施here。
class Key<T> { public Key() { } }
class PolyDictionary {
private Dictionary<object, object> _table;
public PolyDictionary() {
_table = new Dictionary<object, object>();
}
public void Add<T>(Key<T> key, T value) {
_table.Add(key, value);
}
public bool Contains<T>(Key<T> key) {
return _table.ContainsKey(key);
}
public void Remove<T>(Key<T> key) {
_table.Remove(key);
}
public bool TryGetValue<T>(Key<T> key, out T value) {
object objValue;
if (_table.TryGetValue(key, out objValue)) {
value = (T)objValue;
return true;
}
value = default(T);
return false;
}
public T Get<T>(Key<T> key) {
T value;
if (!TryGetValue(key, out value))
throw new KeyNotFoundException();
return value;
}
public void Set<T>(Key<T> key, T value) {
_table[key] = value;
}
}
答案 2 :(得分:1)
你应该能够做出类似以下的事情
interface IItem { object Value {get; set;}}
interface IItem<T> : IItem { T Value {get; set;}}
var items = new List<IItem>();
items.add(new IItem<string>());
items.add(new IItem<int>());
但是当你拔出它时,你仍然需要进行一些施法。
答案 3 :(得分:0)
创建一个新类,其唯一目的是装箱您感兴趣的值。 - 此类应接受StringItem或NumberItem。 - 该类应允许您访问字符串或数字项成员。
当您将对象添加到列表中时,您需要将对象装箱,然后在再次取出时将其取消装箱。
如果这是C ++,那么这个设计的开销不应该超过额外的指针取消引用,这取决于你如何实现它,但是这里的关键短语是“装箱”和“拆箱”。
答案 4 :(得分:0)
public class GrabBag<T>
{
private ArrayList inner = new ArrayList();
public void Add(T item)
{
inner.Add(item);
}
public IEnumerable<U> Get<U>() where U : T
{
return inner.OfType<U>();
}
}
或者,您可以使用通用List并调用OfType。这更有意义。