C#泛型和派生

时间:2018-11-12 17:33:22

标签: c# generics derived-class

我一直在浏览有关该主题的几篇文章,找不到以下问题的合适答案……

谁能告诉我为什么它不能编译:

class MyItem {
    public int ID;
}
class MyList<T> {
    public List<T> ItemList;
}


class MyDerivedItem : MyItem {
    public string Name;
}
class MyDerivedList<MyDerivedItem> : MyList<MyDerivedItem> {
    public int GetID(int index) {
        return ItemList[index].ID; // ERROR : MyDerivedItem does not contain a definition for ID
    }
    public string GetName(int index) {
        return ItemList[index].Name; // ERROR : MyDerivedItem does not contain a definition for Name
    }
}

2 个答案:

答案 0 :(得分:1)

您对此有一些疑问,这首先是您的通用签名。

虽然class MyDerivedList<MyDerivedItem> : MyList<MyDerivedItem>看起来像是使用MyDerivedItem作为类型的泛型类声明,但是您实际上已经声明了使用MyDerivedItem作为泛型类型参数名称的泛型类

您要寻找的是class MyDerivedList<T> : MyList<T> where T : MyDerivedItem,它将为您的下一个交换第一个问题,这是您的其他类型的属性对此不易访问。

class MyItem
{
    public int ID;
}
class MyList<T>
{
    public List<T> ItemList;
}

class MyDerivedItem : MyItem
{
    public string Name;
}

好的,现在属性可以访问的程度足以从MyDerivedList类进行访问,但是还有一个要纠正的问题。 int GetName(int index)应该为string GetName(int index),因为Name属性是一个字符串。

结果如下:

class MyDerivedList<T> : MyList<T> where T : MyDerivedItem
{
    int GetID(int index)
    {
        return ItemList[index].ID;
    }
    string GetName(int index)
    {
        return ItemList[index].Name; 
    }
}

应该编译的很好。

答案 1 :(得分:0)

乔纳森的答案是正确的,但提出的解决方案可能并非您想要的。

也许您只是想要一个继承封闭型通用类型的非通用类型:

class MyDerivedList : MyList<MyDerivedItem>

现在您的代码将按预期工作:

 class MyDerivedList : MyList<MyDerivedItem>
 {
    int GetID(int index)
    {
        return ItemList[index].ID;
    }

    string GetName(int index)
    {
        return ItemList[index].Name; 
    }
}

与您的尝试相反,在MyDerivedItem以上的代码中,实际上是类型MyDerivedItem,而不是通用类MyDerivedList<>的通用类型参数。

令人困惑?是的,这就是为什么您应该避免使用类型名称来命名泛型类型参数,否则可能会伤到您的头;您的代码与以下代码完全相同:

class MyDerivedList<T> : MyList<T> 

但是,T是泛型类型参数而不是具体类型的事实已经显而易见。