Кастинг проблем с подключенными родовыми классами

2

Здесь утонченная версия классов, которые у меня есть.

public abstract class BaseParent { }

public abstract class ChildCollectionItem<T>
  where T : BaseParent
{
  // References a third-party object that acts as the parent to both the collection 
  // items and the collection itself.
  public T parent;

  // References the collection to which this item belongs. The owning collection
  // will share the same parent type. The second type argument indicates what
  // type of items the collection will store. 
  public ChildCollection<T, ChildCollectionItem<T>> owningCollection;
}

public abstract class ChildCollection<T, U> : CollectionBase
  where T : BaseParent
  where U : ChildCollectionItem<T>
{
  // References a third-party object that acts as the parent to both the collection 
  // items and the collection itself.
  public T parent;

  // Adds an item of type 'U' to the collection. When added, I want to set the 
  // owningCollection value of the item to 'this' collection.
  public int Add(U item)
  {
    int indexAdded = this.List.Add(item);

    // THIS LINE IS THROWING A COMPILE ERROR - Cannot convert type 
    // 'ChildCollection<T, U>' to 'ChildCollection<T, ChildCollectionItem<T>>'
    item.owningCollection = this;

    return indexAdded;
}

Я понимаю, что эта проблема, вероятно, связана с тем, что класс ChildCollection не знает ограничений типа, установленных в ChildCollectionItem, потому что, если бы это было, здесь не было бы проблем. Тип 'U' всегда должен быть элементом ChildCollectionItem, где ChildCollectionItem 'T' всегда совпадает с ChildCollection 'T'.

Мне нужно знать, есть ли способ, которым я могу использовать 'this', чтобы он компилировал или изменял мои классы/ограничения, чтобы компилятор мог справиться с этим без приведения.

  • 0
    Кажется, здесь есть синтаксическая ошибка: public int Add <U item>
  • 0
    Спасибо за улов - только опечатка в моем посте, а не код, с которым я работаю. Вся эта работа с дженериками поставила мне в угол угловые скобки.
Теги:
generics
casting

3 ответа

4

Проблема заключается в дисперсии - U может быть другим типом, кроме как только ChildCollectionItem<T> - это может быть тип, полученный из ChildCollectionItem<T>, а Foo<DerivedClass> несовместим с Foo<BaseClass>.

Как насчет введения другого базового класса в ChildCollection<T, U>?

using System.Collections;

public abstract class BaseParent { }

public abstract class ChildCollectionItem<T>
  where T : BaseParent
{
  public T parent;

  public ChildCollection<T> owningCollection;
}

public abstract class ChildCollection<T> : CollectionBase
  where T : BaseParent
{
}

public abstract class ChildCollection<T, U> : ChildCollection<T>
  where T : BaseParent
  where U : ChildCollectionItem<T>
{
  public T parent;

  public int Add(U item)
  {
    int indexAdded = this.List.Add(item);
    item.owningCollection = this;
    return indexAdded;
  }
}
  • 0
    Я не знал, что у тебя могут быть разные типы с одним и тем же именем. Ум: взорван.
  • 0
    Ну, я чувствую, что вы приближаете меня к решению здесь. Но теперь, когда я это сделал, член owningCollection в ChildCollectionItem <T> не может получить доступ к членам производного класса ChildCollection <T, U>, таким как Add (), или другим методам, которые я ранее не использовал в этом примере. - Содержит (), Remove () и т. Д. И снова, я получаю ошибку (теперь во время выполнения) при попытке преобразовать owningCollection из ChildCollection <T> в ChildCollection <T, U>. Я предполагаю, что это по той же причине, что я получил другую ошибку.
Показать ещё 4 комментария
4

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

Вышеприведенное утверждение неверно.

Тип 'U' всегда должен быть ChildCollectionItem, где ChildCollectionItem 'T' всегда является то же, что и ChildCollection 'T'.

Как вы это понимаете? U гарантируется через его ограничение, чтобы быть конвертируемым посредством эталонного преобразования в этот тип. Не гарантируется такой тип, который требуется. U может быть любым типом, полученным из этого типа.

Если U всегда является типом, то почему именно "U" в первую очередь? Почему бы не просто полностью исключить параметр типа и заменить все его использование тем типом, который вы ожидаете?

  • 0
    Я понимаю, что вы говорите, но вот по сути то, что я пытаюсь достичь. Я пытаюсь создать абстрактные классы для коллекции и пары элементов коллекции, которые отвечают следующим требованиям. 1) Объект коллекции и объект элемента должны иметь один и тот же родительский тип. 2) Коллекция строго типизирована для классов, которые наследуются от нее. 3) Абстрактные классы включают код, который поддерживает их синхронизацию друг с другом. В приведенном выше примере, когда я добавляю элемент в коллекцию, в классе элемента устанавливается ссылка, указывающая на эту коллекцию. Пример для подражания ...
  • 0
    Например, мне могут понадобиться классы Comment и CommentCollection, принадлежащие родительскому объекту ForumPost. Я хотел бы иметь возможность: public Class ForumPost: BaseParent {} public class Comment: ChildCollectionItem <ForumPost> public class CommentCollection: ChildCollection <ForumPost, Comment> Коллекция будет строго типизирована для объектов Comment. Родителем объектов Comment и CommentCollection будет ForumPost.
0

Ваше ограничение на U очень специфично; U должен иметь тип ChildCollectionItem. Можно ли в вашем приложении определить коллекцию как

public abstract class ChildCollection<T, ChildCollectionItem<T>>

Это избавит вас от необходимости бросать.

  • 2
    Это не официальное объявление класса.
  • 0
    Ок, стою исправлюсь ....

Ещё вопросы

Сообщество Overcoder
Наверх
Меню