Trójwymiarowa tablica to jakiś żart. Skoro każdy jej wymiar odpowiada jakiemuś elementowi biblioteki, to - zgodnie z DDD (Domain Driven Design) - powinien być opakowany w klasę.
Zatem widzę coś takiego (BTW zwykle wszystkie nazwy powinny być po angielsku, żeby potem nie tworzyć potworków typu GetKsiążka):
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class BookModel
{
public string Author { get; }
public string Title { get; }
public int? Index => Parent?.GetBookIndex(this);
public ShelfModel Parent { get; set; }
public BookModel(string author, string title, ShelfModel parent)
{
Author = author ?? throw new ArgumentNullException(nameof(author));
Title = title ?? throw new ArgumentNullException(nameof(title));
Parent = parent ?? throw new ArgumentNullException(nameof(parent));
parent.AddBook(this);
}
public override string ToString() => $"{Author} {Title}";
}
class ShelfModel
{
public int Index => Parent.GetShelfIndex(this);
public BookcaseModel Parent { get; }
public string Description { get; }
private List<BookModel> books = new List<BookModel>();
public ShelfModel(string description, BookcaseModel parent)
{
Description = description;
Parent = parent;
parent.AddShelf(this);
}
public void AddBook(BookModel book) => books.Add(book);
public IEnumerable<BookModel> Find(string author = null, string title = null)
=> books.Where(b => (title == null || b.Title == title) && (author == null || b.Author == author));
public int GetBookIndex(BookModel bookModel) => books.IndexOf(bookModel);
public override string ToString() => Description;
}
class BookcaseModel
{
public int Index => Parent.GetBookcaseIndex(this);
public string Description { get; }
public LibraryModel Parent { get; }
private List<ShelfModel> shelves = new List<ShelfModel>();
public BookcaseModel(string description, LibraryModel parent)
{
Description = description;
Parent = parent;
Parent.AddBookcase(this);
}
public void AddShelf(ShelfModel shelf) => shelves.Add(shelf);
public IEnumerable<BookModel> Find(string author = null, string title = null) => shelves.SelectMany(s => s.Find(author, title));
public int GetShelfIndex(ShelfModel shelf) => shelves.IndexOf(shelf);
public override string ToString() => Description;
}
class LibraryModel
{
private List<BookcaseModel> bookcases = new List<BookcaseModel>();
public string Description { get; }
public LibraryModel(string description)
{
Description = description;
}
public int GetBookcaseIndex(BookcaseModel bookcase) => bookcases.IndexOf(bookcase);
public void AddBookcase(BookcaseModel bookcase) => bookcases.Add(bookcase);
public IEnumerable<BookModel> Find(string author = null, string title = null)
=> bookcases.SelectMany(bc => bc.Find(author, title));
public bool HasBook(string author = null, string title) => Find(author, title).Any();
public override string ToString() => Description;
}
class Program
{
static void Main(string[] args)
{
var library = new LibraryModel("Biblioteka przy piekarni");
var bookcaseA = new BookcaseModel("Ta po lewej", library);
var bookcaseB = new BookcaseModel("Ta po prawej", library);
var shelfA = new ShelfModel("półka w regale A", bookcaseA);
var shelfB1 = new ShelfModel("górna półka w regale B", bookcaseB);
var shelfB2 = new ShelfModel("dolna półka w regale B", bookcaseB);
var book1 = new BookModel("author", "title", shelfB1);
var book2 = new BookModel("author", "other title", shelfB1);
var book3 = new BookModel("other author", "other title", shelfA);
var booksOfAuthor = library.Find("author").ToList();
booksOfAuthor.ForEach(
b => Console.WriteLine($"{b.Author} \"{b.Title}\" regał: {b.Parent.Parent.Index}, półka: {b.Parent.Index}, miejsce: {b.Index}")
);
}
}
}
Oczywiście można to zrobić ładniej, tu raczej chodzi o ideę.
Teraz zobacz, każdy regał i półka może mieć opis i inne dane, dzięki czemu ktoś, kto pierwszy raz odwiedza bibliotekę może szybko je znaleźć.
Każdy regał może mieć różną ilość półek, a półka - różną ilość książek, co trochę bardziej odpowiada rzeczywistości, niż trójwymiarowa tablica.
Książka wie, w którym miejscu półki stoi, półka - w którym regale, a regał - w której bibliotece, zatem po znalezieniu samej książki trywialne jest znalezienie jej lokalizacji.