Как удалить ненужный список, используя лямбда и функциональную парадигму C # - PullRequest
0 голосов
/ 08 октября 2009

Привет, Функциональный C # Друзья,

Так что в этот раз я пытаюсь сжать свой код и писать в более функциональном, лямбда-стиле, а также хотел бы избежать создания ненужных списков и классов и позволить компилятору сделать всю работу за меня. Мне удалось преобразовать небольшой фрагмент кода функциональным способом, но после этого я не представляю, как это сделать.

var errorList = new List<DataRow>();

IEnumerable<DataRow> resultRows = GetResultRows();

resultRows      
     .Filter(row => row.Field<string>("status").Equals("FAILURE", StringComparison.InvariantCultureIgnoreCase))
     .ForEach(row => { errorList.Add(row); });

if (errorList.Count > 0)
{
    var excludedBooks = new List<string>();
    foreach (DataRow row in errorList)
    {
        if (ToUseBooksList.Contains((string)row["main_book"]))
        {
            BookCheckResults.AddRow(string.Format("Error for MainBook {0}, RiskType {1}",
                                                  row["main_book"], row["risk_type"]));
            if (!excludedBooks.Contains((string)row["main_book"]))
            {
                excludedBooks.Add((string)row["main_book"]);
            }
        }
    }
}

Мои методы расширения:

public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
{
    if (collection == null)
        throw new ArgumentNullException("collection");
    if (action == null)
        throw new ArgumentNullException("action");

    foreach (var item in collection)
        action(item);
}

public static IEnumerable<T> Filter<T>(this IEnumerable<T> source, Predicate<T> func)
{
    foreach (var item in source)
    {
        if (func(item))
            yield return item;
    }
}

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

Ответы [ 2 ]

9 голосов
/ 08 октября 2009

С какой стати вы написали собственный метод расширения Filter, когда доступен Where?

4 голосов
/ 08 октября 2009

Метод расширения ForEach обычно не стоит беспокоиться.

Эрик Липперт написал об этом в блоге , и его философское возражение против этого состоит в том, что оно выглядит как выражение без побочных эффектов (как большинство функций Linq), но на самом деле это побочное действие в маскировка.

Если вы хотите выполнить действие для каждого элемента в списке, используйте оператор foreach. Вот для чего это.

Если вы хотите манипулировать списками действий, то вы можете это сделать, но тогда вы хотите IEnumerable<Action>.

Для первой части вашего кода, как насчет:

var errorList = GetResultRows().Where(row => row.Field<string>("status").Equals("FAILURE", StringComparison.InvariantCultureIgnoreCase)
                               .ToList();

У вас есть List<string>, называемый исключенными книгами. Вместо этого используйте HashSet<string>, и вам не нужно проверять, добавлена ​​ли к нему строка:

var excludedBooks = new HashSet<string>();
foreach (DataRow row in errorList)
{
    if (ToUseBooksList.Contains((string)row["main_book"]))
    {
        BookCheckResults.AddRow(string.Format("Error for MainBook {0}, RiskType {1}",
                                              row["main_book"], row["risk_type"]));

        excludedBooks.Add((string)row["main_book"]);
    }
}

Вы также можете отфильтровать список с помощью Where:

var excludedBooks = new HashSet<string>();
foreach (DataRow row in errorList.Where(r => ToUseBooksList.Contains((string)r["main_book"]))
{
    BookCheckResults.AddRow(string.Format("Error for MainBook {0}, RiskType {1}",
                                              row["main_book"], row["risk_type"]));

    excludedBooks.Add((string)row["main_book"]);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...