C#泛型超类型通配符
我在C#中的泛型中遇到了通配符问题。运行我的小示例的第一种方法是使用对象作为泛型类型,因为它是所有事物的基类C#泛型超类型通配符,c#,generics,wildcard,C#,Generics,Wildcard,我在C#中的泛型中遇到了通配符问题。运行我的小示例的第一种方法是使用对象作为泛型类型,因为它是所有事物的基类 public class AttributeManager { private Dictionary<int, AttributeItem<object>> attributes = new Dictionary<int, AttributeItem<object>>(); public v
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;
}
}
公共类属性管理器
{
私有字典属性=新字典();
公共void添加(AttributeItem属性)
{
if(hasAttribute(属性)){
返回;
}
Add(attribute.getKey(),attribute);
}
}
公共抽象类AttributeItem
{
私钥;
私人T属性值;
私有属性管理器属性管理器;
公共属性项(属性管理器属性管理器,int键)
{
this.key=key;
this.attributeManager=attributeManager;
attributeManager.add(this);//此行不起作用
}
公共无效设置值(T newValue)
{
attributeValue=新值;
}
公共T getValue()
{
返回属性值;
}
}
然而,该行:
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
}
}
公共类属性管理器
{
私人字典>();
/**
*如果hasAttribute(AttributeItem)返回false,此方法将添加新的AttributeItem。
*/
公共void添加(AttributeItem属性)
{
if(hasAttribute(属性)){
返回;
}
attributes.Add(attribute.getKey(),attribute);//此行失败
}
}
但正如您所看到的,我不知道我必须在声明中传递什么类型:
Dictionary<int, AttributeItem<????>> attributes
Dictionary您应该有如下内容:
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);
}
}
公共类属性管理器
{
私有字典属性=新字典();
公共void添加(AttributeItem属性)
{
if(hasAttribute(属性)){
返回;
}
Add(attribute.getKey(),attribute);
}
}
最简单的解决方案是在私有字典字段级别消除泛型:
private Dictionary<int, object> attributes = new Dictionary<int, object>();
private Dictionary attributes=new Dictionary();
这样,您的类仍然有一个很好的泛型接口,并且不需要泛型管理器实例
困难的部分是以后从字典中找出有用的东西。您可以使用反射,但我建议您使用Onam和Robert Hahn建议的界面技术。如果这不能解决您的问题,请告诉我们有关您的用例的更多信息
然而,该行:
attributeManager.add(此)
不起作用。它说没有为此调用找到重载方法。我认为>“this”将被强制转换为AttributeItem,因为对象必须是T的超类
你需要了解一下。基本上,仅仅因为T
可转换为基类型并不意味着通用接口是可转换的。这完全取决于接口的用途
在您的例子中,T是一个输入参数,因此它不能是逆变的(启用AttributeItem转换)。否则,编译时契约将允许将对象传递给setValue,这不是有效的替换
根据您需要对AttributeItem执行的操作,您可以定义一个逆变接口,其中只包含AttributeManager所需的通用返回值。但是my AttributeManager也是通用的。但我希望它接受任何类型的属性。我忘了提这一点。啊,是的,我在设计解决方案时遇到了同样的问题,我个人最终重新设计了它。我想您是在试图避免出现在类声明AttributeManager上?是的。我不希望它是通用的太多。我希望它可以接受任何类型的属性。你可以使用一个接口来代替,并更改你的AttributeItem,使它具有where T:YourInterface约束?所以代码看起来像私有字典属性=new Dictionary();也许这有助于说明或思考如何使用通用属性字典,而不仅仅是“添加”。如前所述,由于您除了添加之外什么都不做,因此您也可以轻松地使用上面的DictionaryGree。我的解决方案可能会使事情变得过于复杂,但会给你这种通用的“感觉”。