Хобрук: Ваш путь к мастерству в программировании

Как я могу улучшить читаемость этих операторов linq?

У меня есть иерархическое дерево данных, содержащее объекты класса с именем DataNode.

Каждый DataNode содержит набор Attribute объектов. Каждый Attribute по сути представляет собой пару ключ/значение с некоторыми присоединенными вспомогательными методами. Например, есть вспомогательный метод EqualsCodeIndex(x), который сопоставляет небольшой набор x значений int с this attribute и возвращает true или false. Все ключи и значения являются строками, потому что все это основано на хранилище ключей/значений, содержащемся в текстовом файле.

Чтобы упростить доступ к конкретному DataNode, в классе DataTree есть словарь, который сопоставляет все узлы дерева с уникальным кодом:

Dictionary<string, DataNode> Codes;

Результирующий оператор Linq для получения определенного значения Attribute выглядит следующим образом:

string AttributeValue = dataTree
    .Codes[@"R-1\CHE"]
    .Attributes
    .Single(x => x.EqualsCodeIndex(parentAttribute.CodeIndex))
    .Value.Trim();

Это не так уж плохо, если мне нужно получить только один или два атрибута по коду и индексу кода, но не так хорошо, если мне нужно получить десять или более.

Чтобы попытаться упростить оператор и разрешить возможность EqualsCodeIndex возвращать false для всех атрибутов в коллекции, я добавил метод расширения:

public static string AttributeValueMatching
    (this KeyValuePair<string, DataNode> pair, List<int> codeIndex)
{
    var attribute = pair.Value.Attributes
        .Single(x => x.EqualsCodeIndex(codeIndex))

    return attribute == null ? string.Empty : value;
}

Это упрощает исходный оператор linq до:

string attributeValue
    = dataTree.Codes[@"R-1\CHE"].AttributeValueMatching(codeIndex);

... что лучше, но у меня такое чувство, что я что-то упускаю.


Есть ли проблемы с этим подходом? Есть ли лучший, более чистый подход, о котором я не думал, может быть, лучше использовать индексаторы или, возможно, свободный интерфейс?

09.06.2011

  • Разве подписка на .SingleOrDefault с .Value не требует NRE? 10.06.2011
  • @Kirk: еще лучшая причина для инкапсуляции с помощью метода расширения. Я исправил проблему в примере кода, хотя окончательный результат будет выглядеть иначе. 10.06.2011
  • Что значит вернуть двадцать или тридцать? Создать двадцать новых разных переменных? 10.06.2011
  • @svick: Правильно. На самом деле, это больше похоже на десять; Мне понадобятся все из них (алгоритм, основанный на данных, который использует извлеченные значения, довольно сложен). Я отредактировал, чтобы уточнить. 10.06.2011
  • @Robert, вы редактировали, пока я составлял свой ответ (ниже), вы начинаете с вопроса о читабельности (для которого я думаю, что метод расширения является хорошим ответом ..) и, кажется, отклоняетесь от вопроса о том, что лучше (возможно) вопрос производительности. ... или я что-то пропустил? 10.06.2011
  • @Cos: меня не волнует производительность... Во всяком случае, пока. В основном я ищу умные способы сократить и упростить код поиска. 10.06.2011

Ответы:


1

Я думаю, что сделать его одним методом с двумя параметрами было бы немного лучше:

Codes.AttributeValueMatching(@"R-1\CHE", codeIndex)

Или вы можете создать оболочку с индексатором:

CodesWrapper[@"R-1\CHE", codeIndex]
09.06.2011

2

У меня нет прямого ответа на весь ваш вопрос, но к разделу «проблемы с этим подходом» у меня есть предложение.

Будьте осторожны, связывая операторы после SingleOrDefault(), так как это потенциально может вернуть null. Если вы абсолютно уверены, что у него всегда будет одно значение, возможно, просто вызовите Single() и разберитесь с этим пропущенным ожиданием, если это когда-нибудь произойдет, вместо более общего NullReferenceException.

EDIT При написании сообщения выше вы внесли те же изменения. Продолжать...

09.06.2011

3

Рассматривали ли вы создание метода расширения для Дерево данных?

подобно

public static class DataTreeExtensions
   {
      public static string FetchByAttribute(this DataTree d, string Attribute)
      {
         string AttributeValue = d
                         .Codes[Attribute]
                         .Attributes
                         .Single(x => x.EqualsCodeIndex(parentAttribute.CodeIndex))
                         .Value.Trim();

            return AttributeValue

      }
   }

Это позволит вам повторно использовать «FetchByAttribute» по желанию как:

string myValue = myTree.FetchByAttribute(@"R-1\CHE");

Отредактировано: изменено с DataNode на DataTree...

09.06.2011
  • Это не совсем работает, так как DataNode не владеет словарем Codes; DataTree делает. Но может с некоторыми изменениями быть обычным методом объекта DataTree. 10.06.2011
  • Я искал и взял dataTree как экземпляр DataNode. Я отредактировал свой ответ и думаю, что это сделает то, что вы хотите. 10.06.2011
  • Это близко, хотя я не думаю, что это должен быть метод расширения, поскольку я в любом случае должен ссылаться на дерево. Я уже предложил решение метода расширения в своем первоначальном вопросе, поэтому я думаю, что вы и @svick говорите, просто переместите технику выше в моей иерархии объектов. 10.06.2011
  • @ Роберт, верно. Идея состоит в том, чтобы инкапсулировать его в свой собственный вызов функции, независимо от того, является ли он органическим для объекта или прикрепленным как расширение, не имеет большого значения... Если только ваша потребность в этой функции не ограничена по объему (скажем, вам может понадобиться сделать много, но только на одной странице/формах/контексте... в этом случае вы можете изолировать функцию по пространству имен и ссылаться на нее только при необходимости.Поскольку вы управляете объектом DataTree, на самом деле нет причин не делать его статический метод объекта или даже метод экземпляра. 10.06.2011
  • Новые материалы

    Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
    каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

    Как настроить Selenium в проекте Angular
    Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

    Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
    Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

    Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
    Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

    стройный-i18следующий
    Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..