Очень простое лямбда-выражение - PullRequest
1 голос
/ 25 октября 2011

Ciao всем, я наконец смог переключиться с .NET Framework 2.0 на .NET Framework 4.0.

Я пытаюсь получить некоторый опыт работы с лямбда-выражением и LINQ.

Является ли этоможно перевести это:

for (int cont = 0;cont < args.Length; cont++)
    Console.WriteLine("#" + cont + " " + "<" + args + ">");

в одну строчную лямбда-выражение, или используя LINQ, или даже какую-то другую структуру, о которой я не знаю?Заранее спасибо.

Ответы [ 8 ]

6 голосов
/ 25 октября 2011

Операции LINQ не должны иметь побочных эффектов или выполнять какие-либо действия.Они должны использоваться только для производства IEnumerable<T> другого IEnumerable<T> (или IQueryable<T> другого IQueryable<T> или IEnumerable<T>) (или при агрегировании, например .Max, .All ... aодин результат)

Прочитайте, например, http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx.

(и обратите внимание, что этот вопрос довольно задан на SO ... Прочитайте, например, мой ответ здесь ToList (). ForEach inLinq и посмотрите решение аналогичной проблемы)

Теперь, если вы достаточно ненавидите себя, вы можете сделать это:

strs.Select((p, index) =>
{
    Console.WriteLine("#" + index + " " + "<" + p + ">");
    return true;
}).All(p => p);

Мы используем .All(p => p) to "материализовать "операцию Select.Это потому, что Select является «ленивым» и не будет выполняться, если его никто не будет повторять.

Технически вы можете даже попытаться немного запутать его:

strs.Select((p, index) =>
{
    Console.WriteLine("#" + index + " " + "<" + p + ">");
    return false;
}).Any(p => p);

(All проверяет, что все элементы равны true, и останавливается, если один из элементов равен false, поэтому он должен циклически переключать все из них (потому что мы всегда return true;). Any (как написано) проверяет, что хотя бы одиниз элементов true и затем останавливается (но все наши элементы false, потому что мы делаем return false;, поэтому Any будет циклически повторять все элементы)

Теперь ... Преимуществоиз этих методов по сравнению с ToList мы не «дублируем» Array на List<T> просто для использования «неправильного» метода List<T>. Если ForEach метод List<T>«неправильно», дублируя Array до List, просто чтобы использовать его вдвойне неправильно.

4 голосов
/ 25 октября 2011

Есть кое-что, что вы должны понять в первую очередь. LINQ - это стиль API функциональный . Его основная цель - предоставить простой и лаконичный способ манипулирования последовательностями.

Ваш код может быть написан с использованием LINQ, но это нежелательно: запись материала в поток (например, консоль) лучше всего выполнять в императивном стиле, а ваш запрос пахнет золотым молотом.

3 голосов
/ 25 октября 2011

Не знаю, зачем вам это, но:

   args.ToList().ForEach(i => Console.WriteLine("#{0} <{1}>",
        args.ToList().IndexOf(i),
        i));

Полагаю, вы хотели вывести сам элемент, а не весь список в каждой строке.

И я сделал конструкцию вывода несколько более приятной.

IMO: Ваш оригинальный код быстрее и легче для чтения.

1 голос
/ 25 октября 2011

Это сделает именно то, что вы просили:

    args
        .Select((x, n) => String.Format("#{0} <{1}>", n, args))
        .ToList()
        .ForEach(Console.WriteLine);

Выдает то же, что и ваш код:

#0 <System.String[]>
#1 <System.String[]>
#2 <System.String[]>

Полагаю, вы хотели что-то похожее на это:

var args = new [] { "Apple", "Banana", "Cherry", };

args
    .Select((x, n) => String.Format("#{0} <{1}>", n, x))
    .ToList()
    .ForEach(Console.WriteLine);

Который производит:

#0 <Apple>
#1 <Banana>
#2 <Cherry>
1 голос
/ 25 октября 2011

Я надеюсь, что эти ссылки помогут вам понять и изучить Lambdas и Linq.

MSDN Лямбда-выражения

101 LINQ Примеры

1 голос
/ 25 октября 2011

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

Action doLoop = ()=>{for (int cont = 0;cont < args.Length; cont++)
    Console.WriteLine("#" + cont + " " + "<" + args + ">");}

Но если вы хотите заменить цикл на linq, это возможно, но плохая идея.Linq разработан для кода без побочных эффектов, Console.WriteLine является побочным эффектом.

Если вы хотите использовать linq, но при этом сохранить вызов Console.WriteLine, вы можете написать:

foreach(string s in Enumerable.Range(0,args.Length).Select("#" + cont + " " + "<" + args + ">"))
    Console.WriteLine(s);

Можно было бы злоупотребить Select, чтобы полностью устранить цикл, но это слишком уродливо, чтобы публиковать здесь.

Многие люди определили метод расширения ForEach, с помощью которого код становится:

Enumerable.Range(0,args.Count).ForEach(()=>Console.WriteLine("#" + cont + " " + "<" + args + ">"));

Но мне не нравится этот стиль.

0 голосов
/ 25 октября 2011

ваши аргументы должны быть массивом:

Array.ForEach(args, s => { Console.WriteLine("#" + Array.IndexOf(args, s) + " " + "<" + args + ">"); });
0 голосов
/ 25 октября 2011

Предполагая что-то вроде этого:

string[] args = new string[] { "a", "pippo", "c" };

, вы можете попробовать это:

args.ToList().ForEach(
    p => Console.WriteLine(
        String.Format("# {0} <{1}>", p, args.Length)));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...