我在C#中使用泛型中的通配符时出现问题。让我的小例子运行的第一种方法是使用object作为泛型类型,因为它是所有东西的基类。
public class AttributeManager
{
private Dictionary<int, AttributeItem<object>> attributes = new Dictionary<int, AttributeItem<object>>();
public void add(AttributeItem<object> attribute)
{
if (hasAttribute(attribute)) {
return;
}
attributes.Add(attribute.getKey(), attribute);
}
}
public abstract class AttributeItem<T>
{
private int key;
private T attributeValue;
private AttributeManager attributeManager;
public AttributeItem(AttributeManager attributeManager, int key)
{
this.key = key;
this.attributeManager = attributeManager;
attributeManager.add(this); // this line does not work
}
public void setValue(T newValue)
{
attributeValue = newValue;
}
public T getValue()
{
return attributeValue;
}
}
但是,行:
attributeManager.add(本);
不起作用。它表示此调用没有找到重载方法。我认为“this”将被转换为AttributeItem,因为对象必须是T的超类。 所以我的第一个问题是为什么这个演员不起作用?
我的第二种方法是将AttributeManager更改为使用通配符:
public class AttributeManager
{
private Dictionary<int, AttributeItem<????>> attributes = new Dictionary<int, AttributeItem<????>>();
/**
* This method will add a new AttributeItem if hasAttribute(AttributeItem) returns false.
*/
public void add<T>(AttributeItem<T> attribute)
{
if (hasAttribute(attribute)) {
return;
}
attributes.Add(attribute.getKey(), attribute); // this line fails
}
}
但正如你所看到的,我不知道我必须在声明中传递哪种类型:
Dictionary<int, AttributeItem<????>> attributes
所以我的第二个问题是,我必须使用什么而不是?????
此致 罗伯特
答案 0 :(得分:2)
最简单的解决方案是在私人字典字段级别删除泛型:
private Dictionary<int, object> attributes = new Dictionary<int, object>();
这样你的类仍然有一个很好的通用接口,你不需要一个通用的Manager实例。
困难的部分是稍后从字典中获取有用的东西。您可以使用反射,但我建议您使用Onam和Robert Hahn建议的界面技术。如果这不能解决您的问题,请告诉我们有关您的用例的更多信息。
答案 1 :(得分:0)
你应该有这样的东西:
public class AttributeManager<T>
{
private Dictionary<int, AttributeItem<T>> attributes = new Dictionary<int, AttributeItem<T>>();
public void add(AttributeItem<T> attribute)
{
if (hasAttribute(attribute)) {
return;
}
attributes.Add(attribute.getKey(), attribute);
}
}
答案 2 :(得分:0)
但是,行:
attributeManager.add(本);
不起作用。它表示此调用没有找到重载方法。我以为&gt; “this”将被转换为AttributeItem,因为object必须是T
的超类
您需要了解covariance and contravariance。基本上,仅仅因为T
可转换为基类型并不意味着通用接口。这一切都取决于接口用于什么。
在您的情况下,T是一个输入参数,因此它不能是逆变的(启用AttributeItem转换)。否则,编译时合同将允许将对象传递给setValue,这不是有效的替换。
根据您使用AttributeItem 做所需的内容,您可以使用AttributeManager的所需泛型返回值来定义逆变接口。