2011-10-25 41 views
1

Ciao everyone, 我終於可以從.NET Framework 2.0切換到.NET Framework 4.0。非常容易的lambda表達式

我想獲得關於lambda表達式和LINQ的一些經驗。

是否有可能把這種:

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

成單行lambda表達式,或者使用LINQ,甚至一些其他costruct我是不知道的? 預先感謝您。

+0

你在tryng用'做 「<」 + args'一部分? Args是一個字符串[]數組我認爲,對嗎? – Marco

+0

我認爲在這個例子中,你的代碼是將每個項目寫入控制檯的最佳解決方案。 :)但是你可以使用LINQ來查詢args集合,如果你想對項目做其他事情。 – BigL

+0

我想你想在第二行中用'args [cont]'而不是'args'。 – CodesInChaos

回答

6

LINQ操作不應該有副作用或執行操作。他們應該只用於生產,從IEnumerable<T>另一個IEnumerable<T>(或從另一個IQueryable<T>IQueryable<T>IEnumerable<T>)(或者,如果聚集,像.Max.All ...一個結果)

例如讀取http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx

(請注意,這個問題是相當問及SO ...例如讀取我的答覆這裏ToList().ForEach in Linq,看到了解決類似的問題)現在

,如果你恨自己足夠的,你可以這樣做:

​​

我們使用.All(p => p)爲 「物化」 的Select操作。這是因爲Select是「懶惰」,如果沒有人循環它將不會執行。

從技術上講,你甚至可以嘗試混淆這一點:

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

All檢查,所有的元素都true並停止,如果的一個是false,因此具有循環所有的人(因爲我們總是return true;)。Any(書面)檢查的元件中的至少一個是true,然後停止(但我們所有的元素都是false,becasue我們做return false;所以Any將循環的所有元素)

Now ...這些技術相對於使用ToList的優勢在於,我們不是將Array複製到List<T>,而僅僅是使用List<T>的「錯誤」方法。如果ForEach方法List<T>是「錯誤」,則將Array複製到List只是使用它是雙重錯誤的。

3

我不知道你爲什麼會想這可是:

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

我想你是要輸出的項目本身,而不是在每一行的整個列表。

而且我已經使輸出結構更好一些。

IMO:您的原始代碼更快,更易於閱讀。

+0

謝謝,我認爲你是對的。既然這些是我進入蘭巴的第一步,我只是認爲有更好的解決方案。不過VS2010 intellisense首先展示了「.ToList <>」的方法。它不應該顯示兩個單獨的方法「.ToList <>」和「.ToList()」? –

+1

該方法實際上是'.ToList ()',但是編譯器可以解析''部分,因此您可以將其忽略。 – GvS

1

將它轉換爲lambda表達式並不重要,並且沒用。

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

假設是這樣的:

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

你可以試試這個:

args.ToList().ForEach(
    p => Console.WriteLine(
     String.Format("# {0} <{1}>", p, args.Length))); 
-1

您ARGS必須是一個數組:

Array.ForEach(args, s => { Console.WriteLine("#" + Array.IndexOf(args, s) + " " + "<" + args + ">"); }); 
+1

不等於原始代碼(不適用於重複項目)和較慢(只是'O(n^2)'而不是'O(n)') – CodesInChaos

4

有些事你必須先了解。 LINQ是一個功能風格的API。它的主要目的是提供簡單而簡潔的方法來操作序列。

您的代碼可以使用LINQ寫的,但它是不可取的:寫東西流(如控制檯)最好是在必要的方式進行的,和金色錘子您的要求之嫌。

1

這將不正是你問什麼:

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> 
+0

好吧,代碼看起來比原來要複雜得多。想知道它是否被翻譯成相同的IL代碼 –

+0

好吧,它是一行,它是LINQ。 :-) – Enigmativity