Re: Какой код проще, лучше и почему
От: Silver_s Ниоткуда  
Дата: 02.04.10 12:53
Оценка: +1
Здравствуйте, Ikemefula, Вы писали:

Кстати у Concat не совсем хороший синтаксис получается.
sr.WorkingSegments.Cast<ServiceSegment>()
            .Concat(sr.ProtectionSegments.Cast<ServiceSegment>())
.SelectMany....


Возможно даже так лучше, несмотря на лишние слова. Симметрично.
Enumerable.Concat(
   sr.WorkingSegments.Cast<ServiceSegment>(),
   sr.ProtectionSegments.Cast<ServiceSegment>()
)
.SelectMany...
Re[6]: Какой код проще, лучше и почему
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 02.04.10 15:13
Оценка:
Здравствуйте, Undying, Вы писали:

U>Издеваешься? FirstOrDefault это вообще крайне опасная операция, т.к. если match у нас, к примеру, int


В таких случаях int просто заменяется на int?
... << RSDN@Home 1.2.0 alpha 4 rev. 1466 on Windows 7 6.1.7600.0>>
AVK Blog
Re[7]: Какой код проще, лучше и почему
От: Lloyd Россия  
Дата: 02.04.10 15:17
Оценка:
Здравствуйте, AndrewVK, Вы писали:

U>>Издеваешься? FirstOrDefault это вообще крайне опасная операция, т.к. если match у нас, к примеру, int


AVK>В таких случаях int просто заменяется на int?


Где именно? В типе match или в коллекции items?
Re[8]: Какой код проще, лучше и почему
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 02.04.10 15:40
Оценка:
Здравствуйте, Lloyd, Вы писали:

AVK>>В таких случаях int просто заменяется на int?


L>Где именно? В типе match или в коллекции items?


Где удобнее.
... << RSDN@Home 1.2.0 alpha 4 rev. 1466 on Windows 7 6.1.7600.0>>
AVK Blog
Re[9]: Какой код проще, лучше и почему
От: Lloyd Россия  
Дата: 02.04.10 19:14
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>>>В таких случаях int просто заменяется на int?


L>>Где именно? В типе match или в коллекции items?


AVK>Где удобнее.


И где удобнее в приведенном примере?
Re[10]: Какой код проще, лучше и почему
От: Lloyd Россия  
Дата: 02.04.10 19:32
Оценка: +1
Здравствуйте, Silver_s, Вы писали:

S_>>Ну там тоже можно сделать:

S_>> matches.Select(_=>(int?)_).FirstOrDefault()
S_>А если часто такое писать, то лучше аналог такой функции реализовать:
S_>
S_>public static T? FirstOrNull<T>(this IEnumerable<T> en) where T: struct
S_>{
S_>    return en.Count() > 0 ? (T?)en.First() : null;
S_>}
S_>


Во-первых, коллекция может не вернуть Count(), например если это бесконечная коллекция.
Во-вторых, коллекция не обязана всегда возвращать согласованный результат при разных запросах, например если это L2S-запрос, то при определенном уровне изоляции транзакций, первый Count() может вернуть число отличное от 0, но последующий First — ничего не вернуть.

Если уж нужно что-то подобное, то используйте подход как у Dictionary:
public static bool TryFirst<T>(this IEnumerable<T> src, out T value) {
    try {
        value = src.First();
        return true;
    } catch (InvalidOperationException) {
        value = default(T);
        return false;
    }
}


Хотя этот код тоже далек от идеала: InvalidOperationException вполне может быть выброшен не непосредственно First-ом, а коллекцией src.

Вариант с ручным перебором наверное будет-таки "честнее":
foreach (T elem in src){
    value = elem;
    return true;
}
value = default(T);
return false;
Re[10]: Какой код проще, лучше и почему
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 02.04.10 19:45
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>И где удобнее в приведенном примере?


Каком именно? Здесь массу вариантов приводили.
... << RSDN@Home 1.2.0 alpha 4 rev. 1466 on Windows 7 6.1.7600.0>>
AVK Blog
Re[11]: Какой код проще, лучше и почему
От: Lloyd Россия  
Дата: 02.04.10 20:38
Оценка:
Здравствуйте, AndrewVK, Вы писали:

L>>И где удобнее в приведенном примере?


AVK>Каком именно? Здесь массу вариантов приводили.


В том, который выше по этой ветке.
Re[12]: Какой код проще, лучше и почему
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 02.04.10 21:49
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>В том, который выше по этой ветке.


Их там тоже не один. Ты можешь конкретный вариант привести?
... << RSDN@Home 1.2.0 alpha 4 rev. 1466 on Windows 7 6.1.7600.0>>
AVK Blog
Re[13]: Какой код проще, лучше и почему
От: Lloyd Россия  
Дата: 02.04.10 22:10
Оценка:
Здравствуйте, AndrewVK, Вы писали:

L>>В том, который выше по этой ветке.


AVK>Их там тоже не один. Ты можешь конкретный вариант привести?


Тот, в котором фигурирует FirstOrDefault.
Re[14]: Какой код проще, лучше и почему
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 02.04.10 22:22
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Тот, в котором фигурирует FirstOrDefault.


В нем, скорее всего, проще будет применить FirstOrValue. Ну либо конвертировать в int? matches.
... << RSDN@Home 1.2.0 alpha 4 rev. 1466 on Windows 7 6.1.7600.0>>
AVK Blog
Re[15]: Какой код проще, лучше и почему
От: Sinix  
Дата: 03.04.10 02:52
Оценка: +1
Здравствуйте, AndrewVK, Вы писали:

AVK>В нем, скорее всего, проще будет применить FirstOrValue. Ну либо конвертировать в int? matches.

Давно сделал bool TryGetFirst<T>(this IEnumerable<T> source, out T value) и не мучаюсь с семантикой. Для извращённых сценариев (пока не понадобилось) можно изобрести Option<T> или использовать Lazy<T> в 4-м фреймворке (кстати, может там и Option<T> уже есть?).


А развели-то...
Слово К.О.: С null засада в том, что не всегда очевидно что получили: null как допустимое значение или null как "не найдено".
Re: Какой код проще, лучше и почему
От: sashar2  
Дата: 04.04.10 06:16
Оценка: -3
Здравствуйте, Ikemefula.

С extensions и/или LINQ синтаксисом вариант в плане читаемости проигрывает. В данном случае можно обойтись foreach. Возможно, стоит части кода вынести в отдельные методы, которые стоит назвать по их смыслу. Ниже приведу пример (только пример ) :

    private void Collect(IService sr, ObjectCategories protection)
    {
      foreach (NetworkConnection networkConnection in GetServiceConnections(sr))
        Collect(networkConnection, protection);
    }

    private IEnumerable<NetworkConnection> GetServiceConnections(IService service)
    {
      List<NetworkConnection> networkConnections = new List<NetworkConnection>();

      foreach (ServiceSegment segment in GetServiceSegments(service))
        foreach (NetworkConnection networkConnection in GetSegmentConnections(segment))
          networkConnections.Add(networkConnection);

      return networkConnections;
    }

    private IEnumerable<ServiceSegment> GetServiceSegments(IService service)
    {
      List<ServiceSegment> segments = new List<ServiceSegment>();

      foreach (ServiceSegment item in service.WorkingSegments)
        segments.Add(item);
      foreach (ServiceSegment item in service.ProtectionSegments)
        segments.Add(item);

      return segments;
    }

    private IEnumerable<NetworkConnection> GetSegmentConnections(ServiceSegment segment)
    {
      List<NetworkConnection> networkConnections = new List<NetworkConnection>();

      foreach (SegmentParcel parcel in segment.SegmentParcels)
        if (parcel.NetworkConnection != null)
          networkConnections.Add(parcel.NetworkConnection);

      return networkConnections;
    }


Можно частично перенести на linq extensions:

    private void Collect(IService sr, ObjectCategories protection)
    {
      foreach (NetworkConnection networkConnection in GetServiceConnections(sr))
        Collect(networkConnection, protection);
    }

    private IEnumerable<ServiceSegment> GetServiceSegments(IService service)
    {
      return Enumerable.Concat(service.WorkingSegments, service.ProtectionSegments);
    }

    private IEnumerable<NetworkConnection> GetServiceConnections(IService service)
    {
      return GetServiceSegments(service).SelectMany(s => GetSegmentConnections(s));
    }

    private IEnumerable<NetworkConnection> GetSegmentConnections(ServiceSegment segment)
    {
      return segment.SegmentParcels.Select(s => s.NetworkConnection).Where(s => s != null);
    }
Re[2]: Какой код проще, лучше и почему
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 04.04.10 06:35
Оценка:
Здравствуйте, sashar2, Вы писали:

S>С extensions и/или LINQ синтаксисом вариант в плане читаемости проигрывает. В данном случае можно обойтись foreach. Возможно, стоит части кода вынести в отдельные методы, которые стоит назвать по их смыслу. Ниже приведу пример (только пример ) :


Это очень тяжелый код. Undying показал самое лучше из императивщины.
Re[7]: Какой код проще, лучше и почему
От: Undying Россия  
Дата: 05.04.10 03:56
Оценка:
Здравствуйте, AndrewVK, Вы писали:

U>>Издеваешься? FirstOrDefault это вообще крайне опасная операция, т.к. если match у нас, к примеру, int


AVK>В таких случаях int просто заменяется на int?


Т.е. если у нас есть коллекция int'ов, то ее надо явно преобразовывать в коллекцию Nullable<int>? Это очень удобно?

Функция FirstOrDefault в фрамеворке это ошибка дизайна, если бы вместо нее были бы функции FirstOrNull для коллекций классов и FirstOrNullable для коллекций структур, то проблем не было бы в принципе.
Re[8]: Какой код проще, лучше и почему
От: Lloyd Россия  
Дата: 05.04.10 06:08
Оценка:
Здравствуйте, Undying, Вы писали:

AVK>>В таких случаях int просто заменяется на int?


U>Т.е. если у нас есть коллекция int'ов, то ее надо явно преобразовывать в коллекцию Nullable<int>? Это очень удобно?


U>Функция FirstOrDefault в фрамеворке это ошибка дизайна, если бы вместо нее были бы функции FirstOrNull для коллекций классов и FirstOrNullable для коллекций структур, то проблем не было бы в принципе.


С FirstOrNull проблемы никуда не ушли бы, т.к. null — вполне себе допустимое зачение для ссылочного типа, а значит может встретиться в коллекции.
Да и с FirstOrNullable — непонятно тогда, как работать с коллекцией nullable-ов, ведь Nullable<T> — сама по себе структура.
Re[9]: Какой код проще, лучше и почему
От: Undying Россия  
Дата: 05.04.10 06:25
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>С FirstOrNull проблемы никуда не ушли бы, т.к. null — вполне себе допустимое зачение для ссылочного типа, а значит может встретиться в коллекции.


И сколько раз в жизни ты писал код, в котором при получении первого элемента требовалось разделять ситуации 1) коллекция пуста 2) в коллекции первый элемент null?

Я вот ни разу, и даже задачу где бы это требовалось придумать не могу.
Re[10]: Какой код проще, лучше и почему
От: Lloyd Россия  
Дата: 05.04.10 06:57
Оценка: +1
Здравствуйте, Undying, Вы писали:

L>>С FirstOrNull проблемы никуда не ушли бы, т.к. null — вполне себе допустимое зачение для ссылочного типа, а значит может встретиться в коллекции.


U>И сколько раз в жизни ты писал код, в котором при получении первого элемента требовалось разделять ситуации 1) коллекция пуста 2) в коллекции первый элемент null?


Тогда тем более непонятно зачем вводить FirstOrNull, если он не решает тех проблем, которые есть у FirstOrDefault.
Re: Какой код проще, лучше и почему
От: Undying Россия  
Дата: 05.04.10 07:45
Оценка: :)
Здравствуйте, Ikemefula, Вы писали:

I>Просьба вникнуть в код и найти потенциальные ошибки в каждом случае


Главная проблема чисто функционального подхода, что на нем непонятно как писать сложные алгоритмы.

Вот к примеру алгоритм определения прохождения расписания:


      int certifiedStationIndex = -1;
      StationIntervalWithIndex unexpectedInterval = null;

      Dictionary<Tuple2<int, DateTime>, bool> undoneArrivalIntervals = new Dictionary<Tuple2<int, DateTime>, bool>();
      while (!isFinished)
      {
        while (rawArrivals.Count > 0 || rawDepartures.Count > 0)
        {
          JointIntervalData currentInterval = null;
          int currentStationIndex = -1;
          bool isArrivalInterval = CurrentPassingIsArrival(rawArrivals, rawDepartures);
          if (isArrivalInterval)
          {
            currentInterval = rawArrivals.Dequeue();
            currentStationIndex = FindStationIndex(result.StationPassings, certifiedStationIndex,
              currentInterval.Joint.Id, true, currentInterval.BeginTime, limitDelay);
            if (currentStationIndex == -1)
              continue;
            undoneArrivalIntervals[_.Tuple(currentInterval.Joint.Id, currentInterval.BeginTime)] = true;
          }
          else
          {
            currentInterval = rawDepartures.Dequeue();
            if (undoneArrivalIntervals.Remove(_.Tuple(currentInterval.Joint.Id, currentInterval.BeginTime)))
              continue;
            currentStationIndex = FindStationIndex(result.StationPassings, certifiedStationIndex,
              currentInterval.Joint.Id, false, currentInterval.ConclusionTime.Value, limitDelay);
            if (currentStationIndex == -1)
              continue;
          }

          StationPassing currentStation = result.StationPassings[currentStationIndex];
          // транспорт движется запланировано
          {
            if (currentStationIndex == certifiedStationIndex + 1)
            {
              currentStation.Interval = currentInterval;
              certifiedStationIndex++;
              unexpectedInterval = null;
              if (certifiedStationIndex == result.StationPassings.Length - 1)
              {
                isFinished = true;
                break;
              }
              continue;
            }
          }
          ...
        }

        yield return status;
      }


Объясните как такие задачи решать в чисто функциональном стиле?

Соответственно получается, что даже если виртуозно владеешь функциональным стилем, все равно для записи сложных алгоритмов нужно не хуже владеть стилем императивным.
Re[11]: Какой код проще, лучше и почему
От: Undying Россия  
Дата: 05.04.10 07:49
Оценка:
Здравствуйте, Lloyd, Вы писали:

U>>И сколько раз в жизни ты писал код, в котором при получении первого элемента требовалось разделять ситуации 1) коллекция пуста 2) в коллекции первый элемент null?


L>Тогда тем более непонятно зачем вводить FirstOrNull, если он не решает тех проблем, которые есть у FirstOrDefault.


Не понял ответа. Если разделять ситуации коллекция пуста и первый элемент коллекции null не требуется, то использовать функции FirstOrNull и FirstOrNullable безопасно, в отличии от функции FirstOrDefault.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.