Для меня (или, вероятно, кого-то еще) не редкость иметь список объектов, которые мне нужно перебирать, а затем взаимодействовать со списком свойств. Я использую вложенный цикл, например:
IList<T> listOfObjects;
IList<TProperty> listOfProperties;
foreach (T dataObject in listOfObjects)
{
foreach (TProperty property in listOfProperties)
{
//do something clever and extremely useful here
}
}
Это проверенный временем образец для этой проблемы? Или есть что-то более производительное, более элегантное или просто забавное (при этом, конечно, все еще читаемое и поддерживаемое)?
Приведенный выше код не вызывает у меня улыбки. Может ли кто-нибудь помочь мне порадовать мою петлю?
Спасибо!
Обновление: я использую термин «ботаник» в самом положительном смысле. В определении в Википедии говорится, что «это относится к человеку, который страстно занимается интеллектуальной деятельностью». Под «ботаником» я подразумеваю кого-то, кто озабочен постоянным совершенствованием себя как программиста, находя новые, новые и элегантные способы кодирования, которые являются быстрыми, удобными в обслуживании и красивыми! Они радуются отказу от VB6 и хотят, чтобы умные люди критиковали их код и помогали им усовершенствоваться. (Примечание: они также любят создавать новые слова, оканчивающиеся на -ify).
Заключительное примечание:
Спасибо Dave R, Earwicker и TheSoftwareJedi за то, что отправили меня по пути Linq. Это как раз тот счастливый код, который я искал!
Многие здесь предпочитают говорить о процессе, а не о коде. Непрерывное "зачем ты это делаешь?" в конце концов немного устает. Мне это нравится ;)
Для java-программистов homepages.mcs.vuw.ac.nz/~djp/jql является отправной точкой. Предполагая, что ваши вложенные циклы предназначены для обнаружения условий и совпадений на равенство; выше сделает свое дело. Но не тогда, когда нужны сложные бизнес-правила. Не знаю эквивалента C#, извини, дружище
Пожалуйста, просмотрите обновленное название и описание, чтобы ответить на вопросы Guge.





В таком сценарии мы часто начинаем с фильтрации интересующих нас частей. ваш блок dosomethingclever () обычно начинается в
foreach (T dataObject in listOfObjects)
{
foreach (TProperty property in listOfProperties)
{
if (property.something == "blah")
{ // OK, we found the piece we're interested in...
// do something clever...
}
}
}
Здесь LINQ - ваш друг, позволяющий заменять циклы оператором select. Конечно, вам все равно может понадобиться повторить набор результатов.
Если вам нужно что-то сделать с каждым объектом и каждым свойством, делать нечего. Возможно, у вас получится делать некоторые синтаксически приятные вещи, но нет способа выполнить эту работу.
Если вы работаете только с подмножеством объектов и / или свойств, отфильтруйте их (с помощью linq to objects, если вы используете .net 3.5)!
Вам может понравиться Фильтр / Карта / Уменьшить для ваших наборов как средство введения лучшего синтаксиса для выполнения операций над наборами.
Я думаю, что он работает над каким-то декартовым объединением результатов списков, так что то, что он делал, не нужно критиковать. Он просто ищет более элегантный способ написать это. Вложенные петли - отстой.
@TheSoftwareJedi - Почему вложенные циклы - отстой? Хотелось бы услышать ваши рассуждения.
Во вложенных циклах нет ничего плохого. Они быстрые, удобочитаемые и существуют с тех пор, как разработка программного обеспечения только зародилась.
Поскольку вы хотите выполнять действия при итерации по коллекции, вы можете обнаружить, что LINQ будет интересным средством для изучения:
http://msdn.microsoft.com/en-us/vcsharp/aa904594.aspx
Вы ограничитесь более поздними версиями Framework (начиная с 3.5), но на самом деле вы можете найти подход функционального программирования довольно элегантным. Другие языковые особенности, которые вступают в игру, когда вы идете по этому пути, включают лямбды и анонимные методы, которые сами по себе увлекательны.
Желаю удачи, и я надеюсь, что вам понравится в пути - это отличный подход :)
Замечательный ответ. Конечно, те, кто считает вложенные циклы нечитаемыми, например TheSoftwareJedi, могут счесть их трудными для чтения. Хотя не понимаю почему.
foreach (var pair in from obj in listOfObjects
from prop in listOfProperties
select new {obj, prop})
{
Console.WriteLine(pair.obj + ", " + pair.prop);
}
Похоже, вы пытаетесь декартово объединить два списка и применить предложение where. Вот простой пример, показывающий синтаксис Linq для этого, и я думаю, это то, что вы ищете. list1 и list2 могут быть любыми IEnumerable, ваше предложение where может содержать более подробную логику, а в предложении select вы можете извлечь то, что вам нужно.
var list1 = Enumerable.Range(1, 100);
var list2 = Enumerable.Range(1, 100);
foreach (var item in from a in list1
from b in list2
where a % b == 0
select new { a, b })
{
Console.WriteLine(item);
};
Однако производительность будет идентична тому, что вы опубликовали - нет желания вводить в заблуждение в этом отношении. Я предпочитаю этот синтаксис Linq.
Action<T, TProp> somethingClever = //your clever method
listOfObjects
.SelectMany(
o => listOfProperties,
(o, p) => new {o, p})
.ToList()
.ForEach(x => somethingClever(x.o, x.p));
Это выглядит еще более занудным! О, варианты счастливого кода! Теперь, чтобы убедить руководителя группы разрешить переход на 3.5 :(
Мне нравится трубы и фильтры Айенде, но это намного больше кода, чем встроенный LINQ для простых циклов (я предполагаю, что пример кода в вопросе был тривиальным).
Хотя мне нравится элегантность решений Linq, я думаю, что я бы порекомендовал извлечь внутренний цикл в метод; Ваш код будет выглядеть примерно так:
foreach(dataObject in listOfObjects)
DoSomethingCleverWithProperties(dataObject, listOfProperties);
Мне это кажется более удобным в обслуживании.
Почему этот вопрос начинается с "ботаников кода вызова"? Мне не нравится термин «ботаник». Это сайт для программистов. Являются ли "программисты" неким подмножеством "программистов"? У меня такое ощущение, что мистер Джипстер не относит себя к этой категории, считает ли он себя лучше, чем «ботаники-программисты»?