إيه هو Enumerable؟
معنى الكلمة نفسه (Concept)
- كلمة Enumerable معناها إنك بتتعامل مع أوبجكت تقدر تعد عليه.
- يعني أي حاجة تقدر تعمل عليها for loop أو foreach loop، زي (arrays) أو (lists). الحاجات دي كلها بنسميها Enumerable.
الـ Class
- ده (Static Class) موجود في LINQ بيوفّر Extension Methods للأنواع اللي بتImplement ال Cs IEnumerable.
- مثال: Where وSelect وOrderBy وكل الـLINQ methods المشهورة موجودة في Class اسمه Enumerable.
- يعني Methods دي بتتطبّق على أي حاجة بتImplement الـIEnumerable عشان تقدر تشتغل معاها باستعلامات LINQ.
تحويل الأوبجكت لـ Enumerable
لو عندك أوبجكت وعايز تخليه Enumerable بحيث تقدر تعمل عليه for loop، لازم تعمل بعض الخطوات.
غالبًا انت مش هتحتاج تعملها بايدك كتير، لأن في حاجات جاهزة في .NET بتخليك تقدر تستخدم الموضوع ده بسهولة، لكن الهدف إنك تفهم ازاي الدنيا شغالة في الخلفية.
كود تحويل أوبجكت إلى Enumerable:
لو فرضنا إن عندك class اسمه Employee
بيحتوي على معلومات عن الموظف، زي الراتب الأساسي والبدلات والتأمينات.
وعايزين نخلّي الأوبجكت ده Enumerable، بمعنى إنه يبقى قابل للتعامل معاه في foreach loop عشان نعد كل بند من بنود الراتب.
public class Employee : IEnumerable<SalaryItem>
{
private List<SalaryItem> salaryItems = new List<SalaryItem>();
public void AddSalaryItem(SalaryItem item)
{
if (item != null)
{
salaryItems.Add(item);
}
}
public IEnumerator<SalaryItem> GetEnumerator()
{
foreach (var item in salaryItems)
{
yield return item;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class SalaryItem
{
public string Name { get; set; }
public double Value { get; set; }
}
-
Employee class:
- الكلاس
Employee
بيحتوي على List من SalaryItem اللي بتمثل بنود الراتب. - عندنا ميثود اسمها
AddSalaryItem
عشان نضيف بنود الراتب، ودي بناديها لما يكون عندك بند راتب جديد عايز تضيفه. - الميثود
GetEnumerator
هي اللي بتحول الـEmployee
لـ Enumerable باستخدام yield return. بمعنى تقدر تستخدم foreach عشان تعد البنود اللي جوا الموظف.
- الكلاس
-
SalaryItem class:
- الكلاس ده بيمثل البند الواحد في الراتب، زي “بدل مواصلات” أو “بدل سكن”، وكل بند له اسم وقيمة.
yield Statement:
الكلمة yield في C# هي اللي بتخلينا نعمل custom enumerators، ودي بتسهل علينا إننا نكتب كود بسيط بدل ما نكتب كل الكود اللي بيبني Enumerator من الصفر.
مثلا، لما بنستخدم yield return، كل مرة بنعمل foreach loop، بنرجع عنصر من عناصر القائمة ونكمل الدورة.
private IEnumerable<int> TestYield()
{
yield return 1;
yield return 2;
yield return 3;
}
لما نعمل foreach على الدالة دي، هيتم طباعة الأرقام 1، 2، 3 بالتتابع، وده لأن yield return بيشتغل زي Enumerator جاهز بيعد علينا القيم اللي بنرجعها.
الفرق بين Enumerator العادي و yield:
الـ Enumerator العادي بيتطلب إنك تبني كل حاجة بنفسك، زي تحديد (index) والحالة اللي بتكون فيها دلوقتي في التعداد. لكن yield بيخليك تعمل ده بشكل تلقائي وسهل، من غير ما تكتب كل الكود ده بنفسك.
مثال على العادي
خلينا نفترض إن عندنا class بيمثل مكتبة فيها مجموعة من الكتب، وعايزين نعمل Enumerator يسمح لنا بالتنقل بين الكتب واحد واحد.
- نبني كلاس Library اللي بيحتوي على مجموعة من الكتب.
- نعمل Enumerator اللي بيتعامل مع عملية التنقل بين الكتب.
using System;
using System.Collections;
using System.Collections.Generic;
public class Book
{
public string Title { get; set; }
public Book(string title)
{
Title = title;
}
}
public class Library : IEnumerable
{
private List<Book> books = new List<Book>();
// إضافة كتاب جديد للمكتبة
public void AddBook(Book book)
{
books.Add(book);
}
// Implement for GetEnumerator that returns Enumerator
public IEnumerator GetEnumerator()
{
return new LibraryEnumerator(books);
}
}
public class LibraryEnumerator : IEnumerator
{
private List<Book> _books;
private int position = -1; // -1 because the position not yet first item
public LibraryEnumerator(List<Book> books)
{
_books = books;
}
// MoveNext() بتحرك المؤشر على الكتاب اللي بعده
public bool MoveNext()
{
position++;
return (position < _books.Count);
}
// Reset() بتعيد المؤشر للبداية
public void Reset()
{
position = -1;
}
// Current بترجع الكتاب الحالي اللي واقف عليه المؤشر
public object Current
{
get
{
if (position == -1 || position >= _books.Count)
{
throw new InvalidOperationException();
}
return _books[position];
}
}
}
استخدام الـ Enumerator:
public class Program
{
public static void Main()
{
Library library = new Library();
library.AddBook(new Book("C# Programming"));
library.AddBook(new Book("Design Patterns"));
library.AddBook(new Book("Data Structures"));
// استخدام الـ Enumerator العادي
IEnumerator enumerator = library.GetEnumerator();
while (enumerator.MoveNext())
{
Book currentBook = (Book)enumerator.Current;
Console.WriteLine(currentBook.Title);
}
}
}
C# Programming
Design Patterns
Data Structures
الفرق بين Enumerable و Enum و Enumerator
الفرق بين Enumerator و Enumerables و Enums في C# هو في الأساس فرق في الوظيفة والاستخدام، ولكل منهم دور مختلف في البرمجة:
1. Enumerable:
- الوظيفة: أي object في C# يمكن التعامل معاه كـ Enumerable يعني تقدر تعد عليه باستخدام foreach loop.
- الاستخدام: يتم استخدامه مع Data structures مثل (arrays, lists) عشان نقدر نعمل loop على عناصرها. أي حاجة في C# يمكن أن تكون Enumerable لو كان فيها ميثود
GetEnumerator()
.
List<int> numbers = new List<int> { 1, 2, 3 };
foreach (var number in numbers)
{
Console.WriteLine(number);
}
هنا الـ List قابلة للعد، وده لأنها Enumerable.
2. Enumerator:
- الوظيفة: هو الـ Object اللي بيتعامل مع عملية التعداد نفسها (enumeration). بيحدد كيفية التنقل عبر العناصر داخل كائن Enumerable.
- الاستخدام: بيستخدم جوه foreach loop عشان يعد العناصر، وكمان تقدر تستخدمه بشكل مباشر لو عايز تتحكم في عملية التعداد خطوة بخطوة عن طريق الميثودز
MoveNext()
,Current
, وReset()
.
List<int> numbers = new List<int> { 1, 2, 3 };
IEnumerator<int> enumerator = numbers.GetEnumerator();
while (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
}
هنا بنستخدم الـ Enumerator مباشرة للتنقل بين عناصر القائمة.
3. Enum (Enumeration):
اتكلمنا عنه قبل كدا في الـ Cs Enums
- الوظيفة: هو نوع بيانات خاص بيسمح لك بتحديد مجموعة من القيم الثابتة اللي بتكون لها معاني مرتبطة. يستخدم لتحديد خيارات ثابتة، وبيساعد في تحسين قراءة الكود وتجنب الأخطاء في القيم.
- الاستخدام: بيستخدم لما يكون عندك مجموعة محددة ومعروفة من القيم اللي مش هتتغير، زي أيام الأسبوع أو اتجاهات الرياح.
enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }
Days today = Days.Monday;
Console.WriteLine(today);
هنا الـ Enum بيحتوي على قيم ثابتة زي الأيام، وبيسمح لنا نستخدمها بدل ما نكتب نصوص أو أرقام ثابتة.
ملخص الفرق:
- Enumerable: هو أي حاجة تقدر تعد عليها، زي الـ List أو Array، وبيتم استخدامه في foreach loops.
- Enumerator: هو الأداة اللي بتعمل عملية التعداد وتتحكم فيها، زي العداد اللي بيقول لنا نروح للعنصر اللي بعده أو نرجع العنصر الحالي.
- Enum: هو نوع بيانات بيسمح بتحديد مجموعة من القيم الثابتة اللي بتسهل التعامل مع خيارات ثابتة ومعروفة.