2011-11-17 43 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',因为它只在列表和数组上暴露。 –

相关问题