清单中的C#foreach

时间:2018-12-14 12:30:17

标签: c# list foreach

问这个问题我很愚蠢,但是我很难理解foreach。举例来说,我正在制作一个Book Store应用程序,同时具有Book类和Inventory类。 Inventory类具有removeBook方法,该方法可从清单中删除一本书。该方法的参数为int bookID。我想我应该使用foreach来完成此任务。我了解foreach的最基本用法,但是我不知道如何使用它来基本上选择特定的bookID,该方法是该方法中的一个参数。有人可以帮我指出正确的方向吗?

这是一个代码段,我知道该方法是错误的:

List<Book> Books = new List<Book>
{
    new Book{ bookID = 5, Name = "Moby Dick", Price = 20.00 },
    new Book{ bookID = 2, Name = "50 Shades of Grey", Price = 0.99 }
}; 

public void removeBook(int bookID)
{
    foreach (var bookID in Books)
    {
        Products.Remove(book);
    }
}

6 个答案:

答案 0 :(得分:3)

从集合中删除东西并不是foreach的目的-它是对集合中的每个值执行一些操作。如果您要删除具有特定ID的图书,则可以使用常规的for循环:

// in Inventory class having List<Book> Books,
// assuming Book has a public int Id property
public void RemoveBook(int bookId) {
    for (int i = 0; i < this.Books.Count; i++) {
        if (this.Books[i].Id == bookId) {
            this.Books.RemoveAt(i);
            return;
        }
    }
}

如果由于某种原因(不应该是-ID应该是唯一的)存在任何重复项,并且您想删除所有具有给定ID的书籍,则此代码应执行以下操作:

public void RemoveBooks(int bookId) {
    // iterating from the end of the array
    // to prevent skipping over items
    for (int i = this.Books.Count - 1; i >= 0; i--) {
        if (this.Books[i].Id == bookId) {
            this.Books.RemoveAt(i);
        }
    }
}

编辑:由于Gerardo Grignoli

,修复了代码

答案 1 :(得分:2)

因此,如果您要从列表中删除一本书,则不必使用foreach循环。最简单的方法是在List上使用RemoveAll函数。

public void RemoveBook(int bookId) =>
    Books.RemoveAll(book => book.Id == bookId);

答案 2 :(得分:0)

函数看起来像这样

void RemoveBook(int bookId)
{
    foreach(Book book in booksRepository)
    {
        if(book.Id == bookId)
        {
            [here you have your method of choice of removing book from container]
            //so for example if your container is list it could look like
            //booksRepository.Remove(book)
        }
    }
}

但是,如果您正在寻找优雅的解决方案,则应考虑使用Linq

答案 3 :(得分:0)

foreach如果要遍历同一列表,将无法正常工作,因此请使用for循环或linq

MSDN

  

foreach语句用于遍历集合以获取所需的信息,但不能用于在源集合中添加或删除项,以避免不可预期的副作用。如果需要从源集合中添加或删除项目,请使用for循环。

private void RemoveBookFromInventory(int bookID)
{
    foreach(Books book in listOfBooks)
    {
         if(book.bookID == bookID)
         {
            listOfBooks.Remove(book); //wont work
         }
    }

    for(int i=0;i<listOfBooks.Count();i++)
    {
        if (listOfBooks[i].bookID == bookID)
            listOfBooks.Remove(listOfBooks[i]);
    }
}

答案 4 :(得分:0)

如果有

List<Thing> things = ....

然后在这样的foreach中

foreach (Thing theThing in things)
{
   // do something with "theThing"
}

foreach遍历things列表中的所有项,并为每个连续值执行该代码块(在{ }之间),该代码块存储在{{1}中}变量(类型为theThing)。

您可以将Thing替换为Thing theThing,以获得完全相同的结果。

答案 5 :(得分:0)

正如其他人所暗示的那样,在使用for循环遍历列表时,您不能真正更改列表的内容,因为那样会更改您正在处理的数据结构。

不过,还有其他几种方法可以解决此问题。我个人喜欢这种风格的解决方案,您首先要获取该书的索引,然后在另一个步骤中将其删除:

var bookID = 2;

int? index = Books     
              // Generate a list of book- and position- pairs:
              .Select((book, pos) => new {book, pos}) 
              // First matching pair (or null):
              .FirstOrDefault(set => set.book.bookID == bookID)? 
              // If NULL was not returned, get the index property:
              .pos;

// Removal is only attempted if a matching book was found:
if(index.HasValue){
    Books.RemoveAt(index.Value);
}