C# .NET 4.0和泛型技术

3

我想知道在C# 4.0中是否可能出现这种行为。

我有一个对象层次结构,我想保持强类型。类似于这样:

class ItemBase {}

class ItemType<T> where T : ItemBase 
{
   T Base { get; set; }
}


class EquipmentBase : ItemBase {}
class EquipmentType : ItemType<EquipmentBase> {}

我希望能够像这样实现以下功能:

ItemType item = new EquipmentType();

我希望item.Base返回类型为ItemBase。基本上,我想知道它是否足够聪明地将强类型泛型转换为基类而不需要强类型。这样做的好处是,我可以简单地将ItemType转换回EquipmentType,并再次获得所有强类型。

也许我的想法有误...

3个回答

4
您在谈论协方差,它可以让您做到以下操作:
ItemType<object> item = new EquipmentType();

由于以下原因,您无法在C# 4中执行此操作:
  1. 泛型协变仅适用于接口、数组和委托类型,而不适用于基类。
  2. ItemType类使用T作为输入/输出类型参数,这意味着它接收一个T并返回一个T。
问题的主要原因是第二个原因,因为如果允许,则以下代码必须可以编译,但在运行时会失败。
// this will not work
ItemType<object> item = new EquipmentType();
item.Base = new Object(); // this seems ok but clearly isn't allowed

协变性和逆变性FAQ


0

我认为C# 4.0的新功能不会对你有所帮助。然而,自从引入泛型以来,已经有一种解决方法:创建一个与泛型类同名的抽象基类,并将所有你想要的成员放在其中,这些成员不需要接受或返回泛型类型的参数,像这样:

class ItemBase {
}

abstract class ItemType {
    public ItemBase Base {
        get { return GetItemBase(); }
        set { SetItemBase(value); }
    }

    protected abstract void SetItemBase(ItemBase value);

    protected abstract ItemBase GetItemBase();
}

class ItemType<T> : ItemType where T : ItemBase {
    protected override sealed void SetItemBase(ItemBase value) {
        Base = (T) value;
    }

    protected override sealed ItemBase GetItemBase() {
        return Base;
    }

    public new T Base { get; set; }
}

0

不行,因为对于编译器来说,ItemType 是一个独立的类型,与 ItemType<EquipmentBase>ItemType<Foo> 不同。所有三个都被视为唯一的类型,它们不能代表彼此。

在你的类声明中,你将其声明为 ItemType<T>,所以 ItemType 将是一个未定义的类型,无法编译。

最好的情况是,你可以使用一个 ItemType<EquipmentBase> 对象来表示 EquipmentType 或任何其他从 ItemType<EquipmentBase> 派生的类,但不能表示 ItemType<PersonType>


1
由于我在答案中提到的两个原因,即使在C# 4中,这也不起作用。但是,即使ItemType<T>改为IItemType<T>,它需要T作为输入和输出参数的事实有效地排除了所需的用法。 - Josh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接