Мой дядя самых честных правил программ исходники за так ...

15 мар. 2009 г.

Цикл как самый выразительный способ перебора элементов

С выходом C# 3.0 увеличилось количество способов перебрать элементы коллекции. Но всё же самым выразительным способом перебора элементов остался цикл.

Например, реализуем перебор всех свойств объекта и распечатаем те из них, у которых есть аттрибут DisplayNameAttribute.

using System;

using System.ComponentModel;

using System.Linq;

using System.Reflection;

 

namespace Home.Andir.Examples

{

    class Foo

    {

        [Category("Основные свойства")]

        [DisplayName("Свойство 1")]

        public string Property1 { get; set; }

 

        [Category("Основные свойства")]

        [DisplayName("Свойство 2")]

        public string Property2 { get; set; }

    }

 

    class Program

    {

        static void Main(string[] args)

        {

            Action<PropertyInfo, DisplayNameAttribute> PrintToConsole =

                (p, attr) => Console.WriteLine("\t{0} : {1}", p.Name, attr.DisplayName);

 

            Console.WriteLine("Foo properties (with foreach):");

            foreach (var p in typeof(Foo).GetProperties())

            {

                foreach (var attr in p.GetCustomAttributes(false))

                    if (attr is DisplayNameAttribute)

                        PrintToConsole(p, attr as DisplayNameAttribute);

            }

 

            Console.WriteLine("Foo properties (with foreach+linq 1):");

            foreach (var p in typeof(Foo).GetProperties())

            {

                var attributes = from attr in p.GetCustomAttributes(false)

                          where attr is DisplayNameAttribute

                          select attr as DisplayNameAttribute;

 

                attributes

                   .ToList()

                   .ForEach(attr => PrintToConsole(p, attr));

            }

 

            Console.WriteLine("Foo properties (with linq 1):");

            typeof(Foo).GetProperties()

                .ToList()

                .ForEach(p =>

                {

                    var attributes = from attr in p.GetCustomAttributes(false)

                              where attr is DisplayNameAttribute

                              select attr as DisplayNameAttribute;

 

                    attributes

                       .ToList()

                       .ForEach(attr => PrintToConsole(p, attr));

                });

 

            Console.WriteLine("Foo properties (with linq 2):");

            typeof(Foo).GetProperties()

                .ToList()

                .ForEach(p =>

                {

                    p.GetCustomAttributes(false)

                        .Where(attr => attr is DisplayNameAttribute)

                        .Cast<DisplayNameAttribute>()

                        .ToList()

                        .ForEach(attr => PrintToConsole(p, attr));

                });

 

            Console.ReadKey();

        }

    }

}

На первом месте по читаемости поставлю первый вариант с циклом. На втором месте последний четвёртый конвеерный способ перебора и фильтрации, но читаемость его гораздо хуже и, в первую очередь, из-за невозможности с первого взгляда объяснить сущность происходящего в коде. Остальные варианты в силу их гибридности смотрятся ещё хуже.

Не злоупотребляйте функциональным стилем в пользу читаемости! :-)

1 комментарий:

Публикуются только комментарии, которые показались автору блога заслуживающими внимания.