Использование Lambda выражений и Extensions в C# 3.0. Расширение интерфейса IEnumerable<> для перебора.

Есть задача распарсить строку вида "127.0.0.1, 192.168.0.1" и получить последовательность с елементами типа IPAddress. Для начала нам надо разделить адреса по запятой. После убрать лишние пробелы и в конце получить елементы типа IPAddress. Заодно немешало бы выдать в Trace полученные значения. Я насчитал 4 конструкции foreach. Для сокращения количества кода создадим расширение для интерфейса IEnumerable<>, которое позволит выполнить необходимые операции без конструкции foreach.

У меня вышло так:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; 


namespace System
{
    public delegate void VoidFunc<T>(T arg); 


    public static class ForeachExtensions
    {
        public static IEnumerable<TResult> TakeForeach<T, TResult>(this IEnumerable<T> sequence, Func<T, TResult> func)
        {
            List<TResult> result = new List<TResult>();
            foreach (T item in sequence)
            {
                result.Add(func(item));
            }
            return result;
        } 


        public static IEnumerable<T> TakeForeach<T>(this IEnumerable<T> sequence, Func<T, T> func)
        {
            return sequence.TakeForeach<T, T>(func);
        }
    }
} 

Первый метод служит для перебора коллекции и имеет возможность изменения в результате типа елементов последовательности. Второй метод всего лишь облегченная реализация первого метода, в котором тип елементов исходной последовательности такой же как и тип елементов в результирующей последовательности.

А теперь попробуем распарсить наш список адрессов:

[TestClass]
public class ForeachExtensionsTests
{
    static readonly string testIpList = "127.0.0.1, 192.168.0.1";
    [TestMethod]
    public void IPListParserTestMethod()
    {
        IEnumerable<IPAddress> result = testIpList.Split(',').TakeForeach<string>(
            delegate(string item)
            {
                return item.Trim();
            }).TakeForeach<string, IPAddress>(
                delegate(string address)
                {
                    return IPAddress.Parse(address);
                }).TakeForeach<IPAddress>(
                    delegate(IPAddress address)
                    {
                        System.Diagnostics.Debug.WriteLine(string.Format("IPAddress: {0}", address.ToString()));
                        return address;
                    });
    }
}

 В результате мы получили минимум кода без обьявления локальных переменных и конструкций foreach.

Результат выполнения бедет следующим:

IPAddress: 127.0.0.1

IPAddress: 192.168.0.1

Но это еще не все, нашу конструкцию можно еще упростить передав функцию IPAddress.Parse в качестве параметра для нашего метода а также воспользуемся лямбда выражениями для вызова функции Trim() и вынесем Trace функию в отдельный метод для повторного использования, это будет выглядеть примерно так:

[TestClass]
public class ForeachExtensionsTests
{
    static readonly string testIpList = "127.0.0.1, 192.168.0.1"; 


    public static void TraceIPAddress(IPAddress address)
    {
        System.Diagnostics.Debug.WriteLine(string.Format("IPAddress: {0}", address.ToString()));
    } 


    [TestMethod]
    public void IPListParserTestMethod()
    {
        IEnumerable<IPAddress> result = testIpList.Split(',')
            .TakeForeach<string>(f=>f.Trim())
            .TakeForeach<string, IPAddress>(IPAddress.Parse);
        result.TakeVoidForeach<IPAddress>(ForeachExtensionsTests.TraceIPAddress);
    }
}

В итоге все наши операции поместились в 4 строчки кода, читабельность которых, на порядок выше и все это благодаря новым возможностям C# 3.0, .Net 3.5 и Visual Studio 2008.

Скачать исходный код примера: BlendWorld.Extensions.zip (7,11 kb)


Метки: , , ,
Категории: .Net | C# Extensions | Lambda Expressions | LINQ | Samples

Комментарии закрыты

Об авторе

Name of author Григорий Полищук

.Net программист



Написать мне Send mail

Реклама

Рекомендую

Последние записи

Последние коментарии

Comment RSS

Статистика