C # foreach в списке - PullRequest
       4

C # foreach в списке

0 голосов
/ 14 декабря 2018

Я чувствую себя глупо, спрашивая об этом, но я изо всех сил пытаюсь понять foreach.Скажем, например, что я делаю приложение для хранилища книг, с классом 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 голосов
/ 14 декабря 2018

Как и предполагали другие, вы не можете реально изменить содержимое списка, перебирая его с помощью цикла 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);
} 
0 голосов
/ 14 декабря 2018

Если у вас есть

List<Thing> things = ....

Тогда в таком foreach, как этот

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

foreach перебирает все элементы в списке things и выполняет этот блок кода(между { }) для каждого последовательного значения, которое хранится в переменной theThing (и имеет тип Thing).

Вы можете заменить Thing theThing на var theThing, дляточно такой же результат.

0 голосов
/ 14 декабря 2018

foreach не будет работать, если вы выполняете итерацию по одному и тому же списку, поэтому используйте для цикла или 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]);
    }
}
0 голосов
/ 14 декабря 2018

Удаление элемента из коллекции - это не то, для чего предназначен foreach, а для выполнения какой-либо операции с каждым значением в коллекции.Если вы хотите удалить книгу с определенным идентификатором, вы можете использовать обычный цикл 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;
        }
    }
}

Если есть какие-либо дубликаты по какой-либо причине (не должно быть - идентификаторы должны быть уникальными) иВы хотели удалить все книги с указанным идентификатором, этот код должен это сделать:

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);
        }
    }
}

РЕДАКТИРОВАТЬ: исправил код, благодаря Герардо Гриньоли

0 голосов
/ 14 декабря 2018

Функция будет выглядеть примерно так

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

0 голосов
/ 14 декабря 2018

Поэтому, если вы хотите удалить книгу из списка, вам не обязательно использовать цикл foreach.Простейшим способом было бы использовать функцию RemoveAll в Списке.

public void RemoveBook(int bookId) =>
    Books.RemoveAll(book => book.Id == bookId);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...