LINQ for Searching
Part of the Object Oriented Programming section of Coddy's C# journey — lesson 65 of 70.
Challenge
EasyLet's add powerful search capabilities to your Library System using LINQ! You'll implement methods that let users find books by various criteria - searching by title, filtering by author, and finding available books. LINQ makes these queries elegant and readable.
You'll continue building on your existing project structure:
Book.cs: Keep your Book class withId,Title,Author, andIsAvailableproperties, along with theBorrow()andReturn()methods.User.cs: Keep your User class with borrowing tracking functionality, includingMaxBooks,CanBorrow(), and the methods for managing borrowed books.Library.cs: This is where you'll add your LINQ-powered search methods. In addition to your existing borrowing logic, implement these search capabilities:SearchByTitle(string keyword)- Returns all books where the title contains the keyword (case-insensitive)GetBooksByAuthor(string author)- Returns all books by a specific author (exact match, case-insensitive)GetAvailableBooks()- Returns all books that are currently availableGetBorrowedBooks()- Returns all books that are currently borrowed
Program.cs: Process search queries and display results.
You will receive the following inputs:
- Library name
- Number of books, then each book as
id|title|author - Number of borrow operations to set up initial state, then each as
bookId - A search command in one of these formats:
title|keyword- search books by title keywordauthor|name- get books by authoravailable- get all available booksborrowed- get all borrowed books
For the search results, print each matching book on its own line in the format {Title} by {Author}. If no books match, print No books found. Results should be printed in the order they appear in the library's collection.
For example, if the inputs are:
City Library
5
B001|The Hobbit|Tolkien
B002|The Lord of the Rings|Tolkien
B003|1984|George Orwell
B004|Animal Farm|George Orwell
B005|The Silmarillion|Tolkien
2
B001
B003
author|TolkienThe output should be:
The Hobbit by Tolkien
The Lord of the Rings by Tolkien
The Silmarillion by TolkienAnother example with the same library setup but searching for available books:
City Library
5
B001|The Hobbit|Tolkien
B002|The Lord of the Rings|Tolkien
B003|1984|George Orwell
B004|Animal Farm|George Orwell
B005|The Silmarillion|Tolkien
2
B001
B003
availableThe output should be:
The Lord of the Rings by Tolkien
Animal Farm by George Orwell
The Silmarillion by TolkienLINQ transforms what would be complex loops into expressive, readable queries. Methods like Where() for filtering and ToList() for materializing results will make your search implementation clean and maintainable!
Try it yourself
using System;
using System.Collections.Generic;
namespace LibrarySystem
{
class Program
{
public static void Main(string[] args)
{
// Read library name
string libraryName = Console.ReadLine();
// Create a Library instance with the library name
Library library = new Library(libraryName);
// Read number of books
int numBooks = Convert.ToInt32(Console.ReadLine());
// Read and add books
for (int i = 0; i < numBooks; i++)
{
string bookInput = Console.ReadLine();
string[] bookParts = bookInput.Split('|');
string bookId = bookParts[0];
string bookTitle = bookParts[1];
string bookAuthor = bookParts[2];
Book book = new Book(bookId, bookTitle, bookAuthor);
library.AddBook(book);
}
// Read number of borrow operations to set up initial state
int numBorrows = Convert.ToInt32(Console.ReadLine());
// Process borrow operations (just book IDs)
for (int i = 0; i < numBorrows; i++)
{
string bookId = Console.ReadLine();
Book book = library.GetBookById(bookId);
if (book != null)
{
book.IsAvailable = false;
}
}
// Read search command
string searchCommand = Console.ReadLine();
// Process search command
List<Book> results = new List<Book>();
if (searchCommand == "available")
{
results = library.GetAvailableBooks();
}
else if (searchCommand == "borrowed")
{
results = library.GetBorrowedBooks();
}
else if (searchCommand.Contains("|"))
{
string[] parts = searchCommand.Split('|');
string searchType = parts[0];
string searchValue = parts[1];
if (searchType == "title")
{
results = library.SearchByTitle(searchValue);
}
else if (searchType == "author")
{
results = library.GetBooksByAuthor(searchValue);
}
}
// Print results
if (results.Count == 0)
{
Console.WriteLine("No books found");
}
else
{
foreach (Book book in results)
{
Console.WriteLine($"{book.Title} by {book.Author}");
}
}
}
}
}
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesNamespaces & DirectivesIntro to Classes & ObjectsThe 'this' KeywordMethods and ParametersFields vs PropertiesConstructorsObject InitializersRecap - Simple Calculator4Inheritance
Basic Inheritance (:) SyntaxThe 'base' KeywordVirtual & Override KeywordsSealed ClassesThe 'object' Base ClassRecap - Employee Hierarchy7Advanced Features
Operator OverloadingIndexers (this[])ToString() OverrideExtension MethodsRecap - Custom List2Properties & Static Members
Auto-Implemented PropertiesRead/Write-Only PropertiesStatic Fields & MethodsStatic ClassesExpression-Bodied Members5Polymorphism & Interfaces
Compile vs Runtime PolyInterface vs Abstract ClassMultiple InterfacesExplicit InterfacesUpcasting & DowncastingRecap - Shape Calculator3Class Architecture
Instance vs Static Data'readonly' & 'const' KeywordsBacking FieldsRecap - Bank Account Manager6Encapsulation
Access ModifiersProperties for EncapsulationData Hiding ImplementationImmutability PatternsRecap - Student Records12Project: Library System
Project StructureBook and User Models