Enumerable.Range - 什么时候使用有意义?

Dan*_*lia 6 .net c# linq

编程时几乎是本能地决定何时使用for循环或foreach,但是选择使用Enumerable.Range的决定因素或问题空间是什么?

一个For循环,当我们要重复的次数后(超过一个简单的数据类型)来计算/做重复的工作选择.

一个对于每个当我们要遍历复杂的对象,计算/做重复性的任务列表相似,但选择.

同样,使用Enumerable.Range的决定因素是什么?

IEnumerable<int> squares = Enumerable.Range(4, 3).Select(x => x * x);
Run Code Online (Sandbox Code Playgroud)

Dam*_*ver 12

foreach是关于迭代现有的集合/集合.

Enumerable.Range用于生成集合/集合.一般来说,你不想编写一个for循环只是为了生成一个集合,如果它可以生成Enumerable.Range- 你只需编写更长的样板代码并要求你分配某种存储(例如a List<int>)来填充.


ReP*_*rre 6

Enumerable.Range()是一个生成器,即它是生成n某种项目的简单而强大的方法。

需要一个包含某个类的随机数量实例的集合吗?没问题:

Enumerable.Range(1,_random.Next())
    .Select(_ => new SomeClass
    {
        // Properties
    });
Run Code Online (Sandbox Code Playgroud)


Me.*_*ame 5

如上所述,Enumerable.Range不是针对循环,而是创建范围.这使得Linq中的一个衬里成为可能,而无需创建子集.这种能力的另一个优点是,你甚至可以在子语句中生成一个子范围,这对于一个for和lambda 来说并不总是可能的,因为在lambdas中不可能产生.

例如,a SelectMany也可以使用Enumerable.Range.测试集合:

class House
{
    public string Name { get; set; }
    public int Rooms;
}

    var houses = new List<House>
    {
        new House{Name = "Condo", Rooms = 3},
        new House{Name = "Villa", Rooms = 10}
    };
Run Code Online (Sandbox Code Playgroud)

当然,这个例子本身并没有多大价值,但是为了获得所有房间,Linq中的实现将是:

   var roomsLinq = houses.SelectMany(h => Enumerable.Range(1, h.Rooms).Select(i => h.Name + ", room " + i));
Run Code Online (Sandbox Code Playgroud)

通过迭代,它需要2次迭代:

   var roomsIterate = new List<string>();
    foreach (var h in houses)
    {
        for (int i = 1; i < h.Rooms + 1; i++)
        {
            roomsIterate.Add(h.Name + ", room " + i);
        }
    }
Run Code Online (Sandbox Code Playgroud)

你仍然可以说,第二个代码更具可读性,但归结为一般使用Linq.


因此,更进一步,我们想要IEnumerable<IEnumerable<string>>所有的房间(每个房间可以容纳一串房间).

LINQ:

listrooms = houses.Select(h => Enumerable.Range(1, h.Rooms).Select(i => h.Name + ", room " + i));
Run Code Online (Sandbox Code Playgroud)

但是现在,在使用迭代时我们需要2个集合:

    var list = new List<IEnumerable<string>>();
    foreach (var h in houses)
    {
        var rooms = new List<string>();
        for (int i = 1; i < h.Rooms + 1; i++)
        {
            rooms.Add(h.Name + ", room " + i);
        }
        list.Add(rooms);
    }
Run Code Online (Sandbox Code Playgroud)

另一个场景,即Linqs和lambdas的优点之一,就是你可以将它们用作参数(例如用于注入目的),这可以通过Enumerable.Range以更简单的方式实现.

例如,你有一个函数,它接受一个参数roomgenerator

static IEnumerable<Furniture> CreateFurniture(Func<House,IEnumerable<string>> roomgenerator){
   //some house fetching code on which the roomgenerator is used, but only the first 4 rooms are used, so not the entire collection is used.
}
Run Code Online (Sandbox Code Playgroud)

上面的房间迭代可以使用Enumerable.Range返回,但是通过迭代,必须首先创建房间的子集合,或者生成结果的单独函数.子集合的缺点是它总是完全填充,即使枚举中只需要一个项目.单独的方法通常是矫枉过正的,因为只需要单个参数使用,因此Enumerable.Range可以节省一天.