如前所述,Enumerable.Range 不是针对循环,而是创建范围。这使得 Linq 中的一个衬垫成为可能,而无需创建子集。
该功能的另一个优势是,您甚至可以在 sub 语句中生成子范围,这对于 for 和 lambda 而言并非总是可行的,因为在 lambda 中无法实现 yield。
例如,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}
};
当然,这个例子本身并没有多大价值,但是为了获得所有房间,Linq 中的实现是:
var roomsLinq = houses.SelectMany(h => Enumerable.Range(1, h.Rooms).Select(i => h.Name + ", room " + i));
如果使用迭代,则需要 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);
}
}
您仍然可以说,第二个代码更具可读性,但这归结为是否使用 Linq。
因此,更进一步,我们需要所有房间的IEnumerable<IEnumerable<string>>(每个房子的房间的可枚举字符串)。
林克:
listrooms = houses.Select(h => Enumerable.Range(1, h.Rooms).Select(i => h.Name + ", room " + i));
但是现在,我们在使用迭代时需要 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);
}
另一个场景,我认为 Linqs 和 lambdas 的一大优点是您可以将它们用作参数(例如,用于注入目的),这可以通过 Enumerable 以更简单的方式实现。范围。
例如,你有一个函数,它带有一个参数 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.
}
上面的房间迭代可以用 Enumerable.Range 返回,但是通过迭代,必须首先创建房间的子集合,或者生成结果的单独函数。
子集合有一个很大的缺点,即它总是被完全填充,即使枚举中只需要一项。单独的方法通常是多余的,因为它只需要使用单个参数,因此 Enumerable.Range 可以节省一天的时间。