在C#中,一个位于List内部的对象如何知道它在列表中的索引位置?

10 浏览
0 Comments

在C#中,一个位于List内部的对象如何知道它在列表中的索引位置?

在C#中,有没有一些我还没有遇到的罕见的语言结构(就像我最近学到的一些,在Stack Overflow上),可以获得表示当前foreach循环迭代的值?

例如,根据情况,我目前做的类似于以下这样的操作:

int i = 0;
foreach (Object o in collection)
{
    // ...
    i++;
}

0
0 Comments

在C#中,如果一个对象位于一个List中,它如何知道自己在List中的索引呢?这个问题的出现是因为枚举的概念与索引的概念是不同的,无法直接获取索引。然而,大多数集合都可以使用索引器和for循环结构进行遍历。以下是解决这个问题的方法:

1. 使用for循环:可以通过使用for循环来遍历List,并使用一个变量来跟踪对象在List中的索引。

for (int i = 0; i < myList.Count; i++)
{
    // 通过i获取对象在List中的索引
}

2. 使用LINQ的Select方法:可以使用LINQ的Select方法将List中的对象与对应的索引组合在一起。这样可以在遍历过程中获取对象的索引。

var indexedItems = myList.Select((item, index) => new { Item = item, Index = index });
foreach (var indexedItem in indexedItems)
{
    // 使用indexedItem.Index获取对象在List中的索引
}

通过以上两种方法,我们可以在遍历过程中获取对象在List中的索引。这样就解决了原问题中对象如何知道自己在List中的索引的问题。

0
0 Comments

在C#中,如果一个对象在一个列表中,它如何知道自己在列表中的索引呢?这个问题的出现是因为需要在遍历一个列表时,同时获取每个元素的索引。解决方法是使用LINQ的Select方法中的重载,该重载可以在遍历列表时返回元素的索引。

以下是解决该问题的代码示例:

foreach (var item in Model.Select((value, i) => new { i, value }))
{
    var value = item.value;
    var index = item.i;
}

这里使用了LINQ的Select方法,通过传入一个lambda表达式,返回一个包含元素索引和值的匿名对象。通过访问该对象的属性,可以获取元素的索引和值。

如果使用的是C# 7.0或更高版本,还可以使用ValueTuple来避免堆分配的开销:

foreach (var item in Model.Select((value, i) => ( value, i )))
{
    var value = item.value;
    var index = item.i;
}

此外,还可以使用自动解构来消除item前缀:

foreach (var (value, i) in Model.Select((value, i) => ( value, i )))
{
    // 在此处直接访问value和i。
}

以上的解决方案适用于在Razor模板中使用,可以方便地获取每个元素的索引。需要注意的是,使用匿名对象会增加额外的内存开销。

这种解决方案使用LINQ的Select方法,该方法的第二个参数表示源元素的索引。关于这个重载的文档可以在这里找到。

有人可能会问,为什么这个解决方案被认为是一个好答案,为什么会有这么多赞(在撰写本文时有超过450个赞)?从我看来,这种方法比简单地增加一个计数器更难理解,不易于维护,占用更多内存,而且可能更慢。我有什么遗漏了吗?对此有人做过性能和内存使用的测试吗?

LINQ的Select方法(带有索引参数)在大多数C#程序员中已经很常见了。只有当你还不熟悉LINQ及其函数式编程风格时,才会感到困惑。

声明循环块内部的变量是低效的。它会导致内存地址的滥用,直到方法结束时都会保留这些变量。

通过使用LINQ的Select方法的重载,我们可以在遍历列表时获取每个元素的索引。这种方法可以提高代码的可读性和简洁性,并且适用于某些特定的场景。然而,需要注意匿名对象会增加额外的内存开销。如果性能和内存使用是重要的考虑因素,可以进行相关的测试和比较。

0
0 Comments

在C#中,如果一个对象在List中,它如何知道它在List中的索引?

C#7.0终于有了一个可以在foreach循环中获取索引的合理语法(即元组):

foreach (var (item, index) in collection.WithIndex())
{
    Debug.WriteLine($"{index}: {item}");
}

需要一个小的扩展方法:

using System.Collections.Generic;
public static class EnumExtension {
    public static IEnumerable<(T item, int index)> WithIndex(this IEnumerable self)       
       => self.Select((item, index) => (item, index));
}

这个答案被低估了,使用元组会更加简洁。

修改以处理空集合:

public static IEnumerable<(T item, int index)> WithIndex(this IEnumerable self) => self?.Select((item, index) => (item, index)) ?? new List<(T, int)>();

为了让习惯于其他语言的人更容易识别,可能将方法命名为Enumerated(并且也可以交换元组参数的顺序)。不过WithIndex本身已经很明显了。

对于空条件,你也可以使用

Enumerable.Empty<(T, int)>()

来代替创建一个空列表,这样效率更高。

0