0

我在 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;
    }
}

但是,该行:

属性管理器.add(this);

不起作用。它说没有找到这个调用的重载方法。我认为“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

所以我的第二个问题是,我必须使用什么来代替 ???????

问候罗伯特

4

3 回答 3

2

最简单的解决方案是在您的私有字典字段级别摆脱泛型:

private Dictionary<int, object> attributes = new Dictionary<int, object>();

这样你的类仍然有一个很好的通用接口,你不需要一个通用的 Manager 实例。

困难的部分是稍后从字典中得到有用的东西。您可以使用反射,但我建议您使用 Onam 和 Robert Hahn 建议的接口技术。如果这不能解决您的问题,请告诉我们更多有关您的用例的信息。

于 2013-07-08T14:17:23.570 回答
0

但是,该行:

属性管理器.add(this);

不起作用。它说没有找到这个调用的重载方法。我认为 > "this" 将被强制转换为 AttributeItem 因为对象必须是 T 的超类

你需要阅读covariance 和 contravariance。基本上,仅仅因为T可转换为基本类型并不意味着泛型接口是。完全取决于接口的用途。

在您的情况下, T 是一个输入参数,因此它不能是逆变的(启用 AttributeItem 演员表)。否则,编译时契约将允许将对象传递给 setValue,这不是有效的替换。

根据您需要对AttributeItem执行的操作,您可能能够使用 AttributeManager 所需的通用返回值定义逆变接口。

于 2013-07-08T15:01:18.260 回答
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);
    }

}
于 2013-07-08T14:09:45.843 回答