|
9 / 9 / 9
Регистрация: 19.09.2011
Сообщений: 272
|
||||||
Преобразование list<type1> в list<type2>23.07.2012, 11:14. Показов 17956. Ответов 13
Метки нет (Все метки)
Здравствуйте, недавно начал изучать с#. Накопилось много вопросов)
но сейчас интересует один конкретный. объём кода - пара сотен строк и дюжина классов...так что думаю, будет проблематично всю сюда свалить (сам вопрос внизу. Описание самой программы можно даже не читать. Читать его нужно только, если то, о чём я спрашиваю - реализовать нельзя.) Смысл такой: будет серия похожих программ, которые сравниваю 2 версии "чего-то там" (хранятся на SQL). Чтобы не писать каждый раз с нуля, я решил сделать 2 части проекта: 1 - базовая часть. Туда входят: -классы, необходимые для распознавания изменений в разных версиях "чего-то там"(нас интересует только великий "БАЗОВЫЙ ТИП", по которому, собственно, и вопрос.) -базовые классы, представляющие общие свойства, методы этого "чего-то там" -интерфейсы и абстрактные классы (один из которых содержит интерфейс доступа к данным SQL базы - назовём его "ConnectorBase") 2 - сменная часть. Туда входят: -производные от базовых классов и интерфейсов из пункта 1. Для нас важны: наследник "БАЗОВОГО ТИПА" - назовём его "ПРОИЗВОДНЫЙ ТИП" и наследник абстрактного класса, отвечающий за доступ к sql серверу (назовём его "Connector"), т.к. именно он и формирует и сам запрос, а также преобразует результат запроса в List<"ПРОИЗВОДНЫЙ ТИП"> Две части связываются вместе с помощью моего собственного простенького "IoC-Контейнера". Как это работает: класс "Connector" создаёт "List<Производный тип>", преобразует его в "List<Базовый тип>" и передаёт классу из части 1 класс из части 1 хранит полученный "List<Базовый тип>" и, с помощью своих методов формирует разные новые List<Базовый тип>, в которые входят некоторые элементы из старого списка. В принципе всё - вот этот новый List<Базового типа> - это ответ, но в последующей части программы, мне нужно преобразовать "ответ" List<Базовый тип> в List<Производный тип>. В этом вся проблемма Решил я пока её плохо - создавать ещё один НОВЫЙ List<Производный тип> и, с помощью foreach и преобразования копировать элементы из List<Базовый> в List<Производный>. Хочется сделать что-то такое
Сам вопрос - можно ли как-то преобразовать List<ПроизводныйТип> в List<БазовыйТип> (ну и наоборот), не прибегая к foreach для каждого элемента списка. (мне уже советовали LINQ выражения, о которых я пока ничего не знаю, но сказали, что принцип его работы такой же, как и у foreach). и далее, если нельзя...то насколько "правильной" можно считать программу (описанную выше) которая для своей работы создаёт ПроизводныйТип, потом преобразует его в БазовыйТип, работает с ним, а, для получения конечного ответа, преобразует его опять же в ПроизводныйТип
0
|
||||||
| 23.07.2012, 11:14 | |
|
Ответы с готовыми решениями:
13
Linq преобразование List<List<double>> в List<Array> Преобразование List<Child> to List<Parent> и обратно
|
|
189 / 189 / 38
Регистрация: 11.04.2009
Сообщений: 497
|
|
| 23.07.2012, 12:05 | |
|
тред не читал@сразу отвечал: см. следующее:
Ковариантность и контравариантность Cast<T> OfType<T>
0
|
|
|
9 / 9 / 9
Регистрация: 19.09.2011
Сообщений: 272
|
||||||||||||||||||||||||||
| 23.07.2012, 14:17 [ТС] | ||||||||||||||||||||||||||
|
Cast<T>
OfType<T> - это пока не смотрел, а вот про Ковариантность и контравариантность почитал. и тут же возник вопрос))
оно же должно работать? p.s.
Если у вас есть иерархия классов, скажем, с типом Employee и типом Manager, производным от Employee (менеджеры — ведь тоже наемные работники), то, как по-вашему, что делает следующий код?
а, понял...тут я пытаюсь использовать контравариантность, полагаясь на пример ковариантности... интерфейс IEnumerable не поддерживает контравариантность, так? Добавлено через 12 минут Итого, пока для себя думаю так: IEnumerable подерживает конвариантность (из производного в базовый) как неявное преобразование. А, чтобы произвести обратное преобразование нужно написать
Если я всё понял правильно,то осталось только понять одну мелочь - после "каста"
тогда как поле "value" переменной "b" Count = 17 означает ли это то, что элементы коллекции c становятся "итераторами", которые при обращении к элементу делают преобразование типа во время выполнения программы?
0
|
||||||||||||||||||||||||||
|
|
||||||||||||
| 24.07.2012, 07:04 | ||||||||||||
|
Ковариантность означает, что можно сделать неявное приведение, даже без Cast.
Вам должно быть важно только то, что тип который возвращает Cast может быть приведен к IEnumerable<T>.
0
|
||||||||||||
|
9 / 9 / 9
Регистрация: 19.09.2011
Сообщений: 272
|
|||||||||||||||||||||
| 24.07.2012, 10:39 [ТС] | |||||||||||||||||||||
|
Ясно. Почитал ещё на msdn про cast и получилось, что я вроде как вернулся к тому, с чего начинал)
т.к. возвращаемое значение каста "Объект IEnumerable<T>, который содержит все элементы исходной последовательности, преобразованные в заданный тип.", что эквивалентно преобразованию каждого элемента через foreach, так? и всё-равно никак не получается заставить работать неявное преобразование. Что не так? 1.)
2.) IEnumerable<T> - это встроенный тип, который объявлён с помощью модификатора out. Поэтому с ним мне ничего делать не надо. И в методах, в качестве типа возвращаемого значения я пишу просто IEnumerable<БАЗОВЫЙ КЛАСС>, за которым у меня скрывается List<Производный класс>. Тут никаких проблем не происходит. Список из производных неявно преобразуется в IEnumerable<Базового>. Это пример ковариантности. 3.) Дальше я поработал с IEnumerable<Базовый> и хочу получить из него IEnumerable<Производный>, для этого пишу
Error 1 Cannot implicitly convert type 'System.Collections.Generic.IEnumerable< VersionInfoBasic.VersionInfoBasic>' to 'System.Collections.Generic.IEnumerable< StrukturaKompleksa.VersionInfoStrukturaK ompleksa>'. An explicit conversion exists (are you missing a cast?) G:\БрЭд\ComparerSolution\ConsoleApplicat ion1\Program.cs 15 79 ConsoleApplication1
0
|
|||||||||||||||||||||
|
|
||||||
| 24.07.2012, 11:04 | ||||||
|
IEnumerable ковариантен (можно делать приведение к базовому типу), но не контрвариантен(можно делать приведение к дочернему тупу).
Поэтому нужен Cast, если вы действительно уверены, что все элементы будут точно дочернего типа.
0
|
||||||
|
9 / 9 / 9
Регистрация: 19.09.2011
Сообщений: 272
|
||
| 24.07.2012, 11:16 [ТС] | ||
|
как почитаю - вернусь ![]() Добавлено через 3 минуты А, "обобщённый" в c# - это "шаблонный" в c++. Щас только разберусь, насколько он будет доверять тому, что в каком-то типе Т будет куча разных методов
0
|
||
|
Master of Orion
|
|
| 24.07.2012, 11:31 | |
|
0
|
|
|
9 / 9 / 9
Регистрация: 19.09.2011
Сообщений: 272
|
|||||||
| 24.07.2012, 11:51 [ТС] | |||||||
|
эх...не хочет компилятор верить, что в каком-то неизвестном, шаблонном типе Т есть какие-то свойства...методы...
например
![]() хотя и защищает от большого кол-ва ошибок Хотел заменить весь Базовый тип на Т, но не получается...т.к. запись, вроде Т.Group или T.Symonyme(t) - невозможны( единственное полезное применение от "обобщения" класса, где определён метод "GetChanged()" я могу получить в том, что уже в самом методе можно будет сделать cast и возвратить список нужного мне типа Осталось только про каст уточнить...
0
|
|||||||
|
|
|||||||
| 24.07.2012, 12:01 | |||||||
|
И тогда он разрешит вызывать все методы, которые есть в VersionInfoBasic.
1
|
|||||||
|
9 / 9 / 9
Регистрация: 19.09.2011
Сообщений: 272
|
||
| 24.07.2012, 12:57 [ТС] | ||
![]() хороший механизм) хотел только поспорить с логикой тех, кто назвал это "ограничением", а базовый object - свободным. (относительно where T : БазовыйКласс и where T : Интерфейс, с остальным тремя(where T : new(), where T : class, where T : struct) согласен - это именно ограничения). Как по мне, object - должен быть самым ограниченным из всех, в том смысле, что у него очень мало возможностей. А любой where - расширяет возможности шаблонного типа, добавляет свойства, поля, методы, и т.д. Кстати в плюсах хотели ввести подобные ограничения (концепты). Но там эта формулировка ("ограничение") больше подходит под смысл самого механизма. Обычный шаблонный тип Т - может всё (свободный), но, стоит добавить концепт и тогда мы ограничим кол-во классов, которые можно подставлять вместо Т.
0
|
||
|
Master of Orion
|
|
| 24.07.2012, 17:47 | |
|
IcyWind, как раз-таки максимально свободным является object, свобода имеется ввиду возможность приведения, то есть если у нас есть массив object, то у нас есть свобода в выборе передаваемого значения (любой класс, любая структура), а если у нас массив какого-то хитрого класса, то только этот класс и его наследники могут передаваться, то есть получается менее обобщенный класс, следовательно менее свободный. Логика как раз-таки правильная. Object является наиболее свободным, т.к. к нему можно привести любой другой класс/структуру.
0
|
|
|
9 / 9 / 9
Регистрация: 19.09.2011
Сообщений: 272
|
|
| 25.07.2012, 10:34 [ТС] | |
|
Убедили
0
|
|
| 25.07.2012, 10:34 | |
|
Помогаю со студенческими работами здесь
14
Как узнать размерность внутреннего вектора в массиве List<List<Double>>? List<string> или все же List<StringBuilder>, что лучше использовать? Необходимо создать dll в которой буду обрабатывать list<list<string>> Найти минимальный элемент List<List<int?>>, не используя циклов List<List<float>> Или как оперировать коллекцией в колекции Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . .
а удачный момент так и не приходит.
|
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица.
Задача: зафиксировать три левых колонки в отчете.
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
/ / . . .
|
Настройки VS Code
Loafer 13.04.2026
{
"cmake. configureOnOpen": false,
"diffEditor. ignoreTrimWhitespace": true,
"editor. guides. bracketPairs": "active",
"extensions. ignoreRecommendations": true,
. . .
|
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2.
Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива.
Было так:. . .
|
|
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2.
Задача: реализовать контроль корректности заполнения дат назначения. . .
|
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html
Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
|
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2.
Задача: при выборе сотрудника (справочник Сотрудники) в ТЧ документа. . .
|
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях.
Задача: при копировании документа очищать определенные реквизиты и табличную. . .
|