C # Обобщение и деривация - PullRequest
0 голосов
/ 12 ноября 2018

Я копался в нескольких сообщениях на эту тему и не смог найти подходящего ответа на следующую проблему ...

Может кто-нибудь сказать мне, почему это не компилируется:

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 голосов
/ 12 ноября 2018

Ответ Джонатона верен, но, возможно, предлагаемое решение не совсем то, что вы хотите.

Может быть, вы просто хотите не универсальный тип, который наследует закрытый универсальный тип:

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 является параметром общего типа, а не конкретным типом, очевиден.

0 голосов
/ 12 ноября 2018

У вас есть несколько проблем с этим, первой из которых является ваша общая подпись.

Хотя 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; 
    }
}

Что должно прекрасно компилироваться.

...