Типизирующие переменные, содержащие экземпляры ограниченных родовых классов - PullRequest
2 голосов
/ 07 декабря 2009

Я только начинаю осваивать дженерики и использую их для рефакторинга довольно сложного раздела моего кода (я только недавно использовал c #, но довольно опытен в других языках).

У меня есть структура наследования, где мои классы расширяют базовый класс. В базовом классе я реализовал большую часть функциональности. Но я хочу иметь возможность связать эти классы детей с экземплярами своих братьев и сестер.

Вот упрощение некоторых соответствующих кодов:

class ParentClass<T>
    where T : ParentClass<T>, new()
{

    public static T Create()
    {
        return new T();
    }

    private object joinedItem;

    public void Join<TJoinee>(TJoinee item)
        where TJoinee : ParentClass<TJoinee>, new()
    {
        joinedItem = item;
    }

}

class ChildOne : ParentClass<ChildOne>
{
}

class ChildTwo : ParentClass<ChildTwo>
{
}

С этим кодом я могу сделать что-то вроде:

var a = ChildOne.Create();
a.Join(new ChildTwo());

Проблема в том, что мне нужно было набрать joinedItem как объект, когда я действительно хочу напечатать его как ParentClass<Something>. Можно ли прописать более конкретный тип для joinedItem? Или я просто ужасно ругаю язык и должен придерживаться совершенно другого подхода?

Ответы [ 2 ]

3 голосов
/ 07 декабря 2009

Не могли бы вы извлечь интерфейс из ParentClass<T>, который не зависит от T? Таким образом, joinedItem можно было бы ввести в интерфейс.

Похоже, что вы можете сделать то, что пытаетесь сделать (соедините ParentClass<T> экземпляров с ParentClass<U> экземплярами).

Если в этом интерфейсе ParentClass<T> нет ничего, что не зависит от T, тогда будет трудно найти более полезный интерфейс, чем объект, не зная T.

1 голос
/ 07 декабря 2009

Основная проблема здесь заключается в том, что невозможно выразить представление о том, что переменная должна иметь тип XYZ<_> - с параметром произвольного типа.

Вы можете выразить это в параметрах, тогда вам просто нужно добавить ограничения (как вы делаете), но вы не можете сделать это к переменным (по крайней мере, без добавления типа переменной в список введите параметры, которые могут быть синтаксически некрасивыми).

Итак, если вам нужно выразить понятие XYZ<_> для любого типа _, вам нужно будет явно представить это понятие как тип (скажем, IXYZ) и убедиться, что все XYZ<_> : IXYZ действительно унаследовать от этого. Как правило, наиболее гибкий способ сделать это - через интерфейс, но абстрактный базовый класс тоже подойдет.

К сожалению, классы типов вообще не являются частью обобщенных типов; -).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...