Вопрос больше теоретический. Но буду признателен и за практическое решение, а дальше, на его основе, смогу додумать.
До сего момента плотно с обобщениями работать не приходилось и уперся в то, что второй день не могу внятно сформулировать Гуглу вопрос и, соответственно, получаю ответы как вот сейчас на вопрос "как вставить текст между <> в редакторе стековерфлоу" - ответы про вставку их как угодно и куда угодно, кроме редактора на сайте :)
Возникла задача
Реализовать некий базовый класс. При этом поля ID и Value - обобщенные, ID ограничено - IConvertible, IComparable
Реализовать коллекцию (наподобие List) для этих элементов, в которой реализованы все необходимые методы работы с элементами
Реализовать коллекцию (наподобие Dictionary) для работы с коллекциями из п. 2, а через них и доступ к элементам из п. 1
(т.е. получается, что пп 2-3 обеспечивают еще и доступ по типу row\column для элемента, но, тем не менее, юзать DataTable или другие встроенные типы - не подходит)
Смысл в том, что элементы содержат все необходимые свойства\методы для разных, но однотипных задача (в основном справочники всякие). И, по задумке - ID может быть цифрой, к которой привязывается Value - строка, или наоборот или ID - строка\цифра\дата - Value класс.
Как следствие - TID, TVаlue элементов указывается так же и для коллекций всех уровней (п.п. 2-3) и, стало быть, если для п.3 создаем MyDic<string, string>
то и все остальное, вплоть до элементов, будет этого типа.
В пп. 2-3 реализован интерфейс IEnumerable.
В итоге получается следующее
StrElm : BaseElm<string, string>
StrLst : BaseLst<string, string>
Уже получается чепуха. Т.к. IEnumerable, реализованный в BaseLst, возвращает BaseElm<TID, TValue>
, а не StrElm.
При этом компилятор итерацию foreach(StrElm el in StrLst)
пропускает, в реалтайме Exception приведения типов.
А если var - то возвращает, соотв. BaseElm<string, string>
, а не StrElm
Вот, собственно, и вопрос. Как бы это обойти.
А, точнее - догадываюсь, что косяк у меня в "архитектуре" оттого, что опыта работы с обобщениями маловато, а сама задача, с виду, "типовая" - организовать работу с элементами с нужным функционалом и уже вчера была бы решена, если бы типы были заранее определенными.
Поэтому и вопрос более "глобальный" - как это реализуется в случае обобщенных типов и где бы об этом почитать ( или глянуть примеры), но, по возможности, под конкретную эту задачу (увы, перечитать Рихтера или, хотя бы, Троелсена, осмыслить обобщения и написать потому как надо уже не успеваю :) )
Честно говоря не совсем понял что вы хотите, лучше хотя бы псевдокодом показать что вы хотите получить если не знаете как это реализовать на целевом языке, но в комментарии код писать ни разу не здорово, поэтому пусть пока повисит в виде ответа.
По описанию вам вероятно нужно что-то такое
class BaseType<TId, TValue> where TId : struct, IConvertible, IComparable
{
public TId Id { get; set; }
public TValue Value { get; set; }
//ваша дополнительная логика
}
class CustomList<TElem, TId, TValue> : List<TElem>
where TId : struct, IConvertible, IComparable
where TElem : BaseType<TId, TValue>
{
//ваша дополнительная логика
}
class CustomDictionary<TKey, TDictVAlue, TElem, TId, TValue> : Dictionary<TKey, TElem>
where TId : struct, IConvertible, IComparable
where TElem : BaseType<TId, TValue>
where TDictVAlue : CustomList<TElem, TId, TValue>
{
//ваша дополнительная логика
}
Но это такое себе решение и действительно попахивает проблемами в архитектуре. Если что-то непонятно - добавлю уточнения, если совсем не попал - совсем удалю.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Пусть нужно сделать проект с многоуровневой архитектуройКак и в каких случаях нужно делать так: Class Libraries: Entites, DLayer, DTO,BLayer, Presenttion Layer, Core или...