2011-11-17 48 views
22

這裏的一個比特的打印出的數字的代碼平方從0到9:在C#中有一個「upto」方法嗎?

for (int i = 0; i < 10; i++) 
    Console.WriteLine(i*i); 

經由for循環做從0到N 1的東西是一個非常普遍的習慣用法。

下面是一個UpTo方法,它表達了這一點:

class MathUtil 
{ 
    public static void UpTo(int n, Action<int> proc) 
    { 
     for (int i = 0; i < n; i++) 
      proc(i); 
    } 
} 

上方正方形比如現在是:

MathUtil.UpTo(10, (i) => Console.WriteLine(i * i)); 

我的問題是,不標準的C#庫來與像上述UpTo

理想情況下,我想要一種方法使'UpTo'成爲所有整數對象的一種方法。所以,我可以這樣做:

var n = 10; 

n.UpTo(...); 

這是可能在C#中?

+13

這可能是一個味道的問題,但我認爲'for'變種比'UpTo'更具可讀性。另外,修改'for'變體中的起始數字('0')或增量方法('i ++')非常容易。我認爲[Eric Lippert對'ForEach'方法的評論](http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx)也適用於此。 – Heinzi

+1

@Heinzi感謝您的鏈接到Eric的文章! – dharmatech

+1

.NET擴展方法(http://dnpextensions.codeplex.com/)有一個擴展方法。 '5×(...);' – Jalal

回答

49

把它變成一個extension method(注意n參數,該參數定義了該方法進行操作的類型前):

static class MathUtil 
{ 
    public static void UpTo(this int n, Action<int> proc) 
    { 
     for (int i = 0; i < n; i++) 
      proc(i); 
    } 
} 

用法:

10.UpTo((i) => Console.WriteLine(i * i)); 

注意:上面的方法調用雖然不是特別直觀。記住代碼只寫一次並閱讀很多次。

也許允許下面的東西可能會稍微好一些,但說實話我仍然只是寫一個foreach循環。如果你想要一個包容性的上限

public static void UpTo(this int start, int end, Action<int> proc) 
{ 
    for (int i = start; i < end; i++) 
     proc(i); 
} 

變化<<=

0.UpTo(10 /*or 9 maybe*/, (i) => Console.WriteLine(i * i)); 

如果你想這一點,那麼你可以寫一個擴展方法是這樣的。

+0

你按時擊敗了我:upvoted! :) – Marco

+6

我知道這是OP所要求的,但語法很臭:'10.UpTo(i => Console.WriteLine(i * i));'...除了事實上,我知道擴展方法和他們買得起的骯髒技巧:) –

+0

@ MerlynMorgan-Graham:注意到。 –

10

試試這個:

public static class IntExtensions 
{ 
    public static void UpTo(this int n, Action<int> proc) 
    { 
     for (int i = 0; i < n; i++) 
      proc(i); 
    } 
} 

有了這個,你可以寫

10.UpTo(i => Console.WriteLine(i * i)); 

我寫的函數被調用的擴展方法
在設計時您注意不是本機功能,因爲它具有不同的圖標。
Estension方法是包含在靜態類中的靜態方法或函數,它們的工作類型是您必須使用關鍵字this的第一個參數。
IntExtensions班,你可以寫所有你喜歡的方法;將它們分組到相同的靜態類中可讓您輕鬆管理它們。

+0

真棒回答,謝謝Marco! – dharmatech

6

嘗試Enumerable.Range,可能結合TakeTakeWhile

IEnumerable<int> values = Enumerable.Range(0, 20) 
    .Take(10); // Not necessary in this example 

foreach(var value in values) 
{ 
    Console.WriteLine(value); 
} 

// or ... 

foreach(var i in Enumerable.Range(0, 10)) 
{ 
    Console.WriteLine(i * i); 
} 

上有List<T>,你可以用更貼近語法你想要什麼ForEach,但我認爲這是不好的形式。它採用純粹的查詢/過濾/轉換語法,以有效的不變方式工作,並引入副作用。

爲了您未來的娛樂,您可能需要查看extension methodsIEnumerable<T>yield return。當你將這三件事組合使用時,許多生成器類型的功能和有趣的語法變得可能。雖然我會爭辯說,這個特定的例子不是使用它們的最佳地方,因爲結果語法變得混亂。

2

讓你的方法是這樣的一個靜態類 「擴展」,例如:

public static void UpTo(this int n, Action<int> proc) 
{ 
    for (var i = 0; i < n; i++) 
     proc(i); 
} 

和使用:

var n = 10; 
n.UpTo(i => Console.WriteLine(i * i)); 

希望這有助於! :)

8

想要在一行嗎?這裏是:

Enumerable.Range(0, 9).Select(i => i * i).ToList().ForEach(j=>Console.WriteLine("%d",j)); 
+1

很酷的回答。 :-) – dharmatech

+4

爲什麼需要ToList()? –

+5

'ToList()'需要調用'ForEach',因爲它只在列表和數組上暴露。 –

相關問題