Хтось може мені пояснити IEnumerable та IEnumerator?
наприклад, коли його використовувати над foreach? яка різниця між IEnumerable та IEnumerator? Навіщо нам це використовувати?
Хтось може мені пояснити IEnumerable та IEnumerator?
наприклад, коли його використовувати над foreach? яка різниця між IEnumerable та IEnumerator? Навіщо нам це використовувати?
Відповіді:
наприклад, коли використовувати його над foreach?
Ви не використовуєте IEnumerable
"понад" foreach
. Реалізація IEnumerable
робить foreach
можливим використання .
Коли ви пишете код, наприклад:
foreach (Foo bar in baz)
{
...
}
це функціонально еквівалентно написанню:
IEnumerator bat = baz.GetEnumerator();
while (bat.MoveNext())
{
bar = (Foo)bat.Current
...
}
Під "функціонально еквівалентним" я маю на увазі саме те, що компілятор перетворює код. Ви не можете використовувати foreach
на baz
в даному прикладі виключення випадків , коли baz
інвентар IEnumerable
.
IEnumerable
означає, що baz
реалізує метод
IEnumerator GetEnumerator()
IEnumerator
Об'єкт, цей метод повертає повинні реалізувати методи
bool MoveNext()
і
Object Current()
Перший метод переходить до наступного об'єкта в IEnumerable
об'єкті, який створив перелік, повертаючись, false
якщо це зроблено, а другий повертає поточний об'єкт.
Що б там не було. Зверніть увагу, що ви можете переглядати програми IEnumerable
. Якщо ви будуєте свій власний клас, і він вже не успадковується від класу, який реалізує IEnumerable
, ви можете зробити свій клас придатним для використання в foreach
операторах, реалізуючи IEnumerable
(і створивши клас перелічувача, який GetEnumerator
поверне його новий метод).
bool MoveNext()
метод та Current
властивість будь-якого типу. Такий підхід «набору качок» був реалізований в C # 1.0 як спосіб уникнути боксу при перерахуванні колекцій типу цінностей.
iterator
?
Інтерфейси IEnumerable та IEnumerator
Для початку вивчення процесу реалізації існуючих інтерфейсів .NET, спочатку розглянемо роль IEnumerable та IEnumerator. Нагадаємо, що C # підтримує ключове слово з назвою foreach, яке дозволяє перебирати вміст будь-якого типу масиву:
// Iterate over an array of items.
int[] myArrayOfInts = {10, 20, 30, 40};
foreach(int i in myArrayOfInts)
{
Console.WriteLine(i);
}
Хоча може здатися, що лише такі типи масивів можуть використовувати цю конструкцію, правда полягає в тому, що будь-який тип, що підтримує метод, який називається GetEnumerator (), може бути оцінений конструктом foreach. Для ілюстрації слідкуйте за мною!
Припустимо, у нас є клас Гараж:
// Garage contains a set of Car objects.
public class Garage
{
private Car[] carArray = new Car[4];
// Fill with some Car objects upon startup.
public Garage()
{
carArray[0] = new Car("Rusty", 30);
carArray[1] = new Car("Clunker", 55);
carArray[2] = new Car("Zippy", 30);
carArray[3] = new Car("Fred", 30);
}
}
В ідеалі було б зручно перебирати підпункти об'єкта Garage за допомогою конструкції foreach, як і масив значень даних:
// This seems reasonable ...
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("***** Fun with IEnumerable / IEnumerator *****\n");
Garage carLot = new Garage();
// Hand over each car in the collection?
foreach (Car c in carLot)
{
Console.WriteLine("{0} is going {1} MPH",
c.PetName, c.CurrentSpeed);
}
Console.ReadLine();
}
}
На жаль, компілятор повідомляє вам, що клас Garage не реалізує метод на ім'я GetEnumerator (). Цей метод формалізований інтерфейсом IEnumerable, який виявляється хованим у просторі імен System.Collections. Класи або структури, що підтримують таку поведінку, рекламують, що вони здатні викривати містять підпункти для абонента (у цьому прикладі саме ключове слово foreach). Ось визначення цього стандартного інтерфейсу .NET:
// This interface informs the caller
// that the object's subitems can be enumerated.
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
Як бачите, метод GetEnumerator () повертає посилання на ще один інтерфейс під назвою System.Collections.IEnumerator. Цей інтерфейс забезпечує інфраструктуру, що дозволяє абоненту перетинати внутрішні об'єкти, що містяться в IEnumerable-сумісному контейнері:
// This interface allows the caller to
// obtain a container's subitems.
public interface IEnumerator
{
bool MoveNext (); // Advance the internal position of the cursor.
object Current { get;} // Get the current item (read-only property).
void Reset (); // Reset the cursor before the first member.
}
Якщо ви хочете оновити тип Garage для підтримки цих інтерфейсів, ви можете пройти довгу дорогу та реалізувати кожен метод вручну. Хоча ви, безперечно, можете надати спеціалізовані версії GetEnumerator (), MoveNext (), Current і Reset (), є більш простий спосіб. Оскільки тип System.Array (як і багато інших класів колекції) вже реалізує IEnumerable та IEnumerator, ви можете просто делегувати запит System.Array таким чином:
using System.Collections;
...
public class Garage : IEnumerable
{
// System.Array already implements IEnumerator!
private Car[] carArray = new Car[4];
public Garage()
{
carArray[0] = new Car("FeeFee", 200);
carArray[1] = new Car("Clunker", 90);
carArray[2] = new Car("Zippy", 30);
carArray[3] = new Car("Fred", 30);
}
public IEnumerator GetEnumerator()
{
// Return the array object's IEnumerator.
return carArray.GetEnumerator();
}
}
Після оновлення типу Garage ви можете сміливо використовувати тип у конструкції forex C #. Крім того, враховуючи, що метод GetEnumerator () визначений публічно, користувач об'єкта також може взаємодіяти з типом IEnumerator:
// Manually work with IEnumerator.
IEnumerator i = carLot.GetEnumerator();
i.MoveNext();
Car myCar = (Car)i.Current;
Console.WriteLine("{0} is going {1} MPH", myCar.PetName, myCar.CurrentSpeed);
Однак якщо ви віддаєте перевагу приховати функціональність IEnumerable від об'єктного рівня, просто скористайтеся явною реалізацією інтерфейсу:
IEnumerator IEnumerable.GetEnumerator()
{
// Return the array object's IEnumerator.
return carArray.GetEnumerator();
}
Роблячи це, випадковий користувач об'єкта не знайде метод GetEnumerator () Garage, тоді як конструкція foreach отримає інтерфейс у фоновому режимі при необхідності.
Адаптовано з Pro C # 5.0 та .NET 4.5 Framework
Garage
який отримує carArray
? Таким чином, вам не доведеться реалізовувати GetEnumerator
себе, оскільки це Array
вже робиться. Напр.foreach(Car c in carLot.getCars()) { ... }
Реалізація IEnumerable означає, що ваш клас повертає об'єкт IEnumerator:
public class People : IEnumerable
{
IEnumerator IEnumerable.GetEnumerator()
{
// return a PeopleEnumerator
}
}
Реалізація IEnumerator означає, що ваш клас повертає методи та властивості для ітерації:
public class PeopleEnumerator : IEnumerator
{
public void Reset()...
public bool MoveNext()...
public object Current...
}
У цьому все-таки різниця.
Спочатку пояснення без коду, потім я додам його згодом.
Скажімо, ви керуєте авіакомпанією. І в кожному літаку ви хочете знати інформацію про пасажирів, які літають в літаку. В основному, ви хочете мати можливість "пройти" літак. Іншими словами, ви хочете мати можливість стартувати на передньому сидінні, а потім пропрацювати свій шлях до задньої частини літака, запитуючи пасажирів деяку інформацію: хто вони, звідки вони і т. Д. Літак може це зробити лише , якщо це:
Чому ці вимоги? Тому що для цього потрібен інтерфейс.
Якщо це перевантаження інформацією, все, що вам потрібно знати, - це те, що ви хочете мати можливість задати кожному пасажиру в літаку деякі питання, починаючи з першого і пробираючись до останнього.
Що означає лічильник?
Якщо авіакомпанія є "рахунковою", це означає, що В ПОВИННІЙ ПЛАНІ повинен бути присутнім стюардеса, яка єдина робота - це рахувати - і ця стюардеса ПОВИННА рахувати дуже конкретно:
Процедури підрахунку
Капітан авіакомпанії хоче отримати звіт про кожного пасажира про те, як і коли вони розслідуються або підраховуються. Тож після розмови з людиною на першому сидінні стюардеса / стійка подає доповідь капітану, а коли дається звіт, лічильник запам'ятовує своє точне положення в проході і продовжує рахувати право, де він / вона пішов вимкнено.
Таким чином капітан завжди може мати інформацію про поточну особу, яку розслідують. Таким чином, якщо він дізнається, що цій особі подобається Манчестер Сіті, то він може надавати цьому пасажиру пільговий режим і т.д.
Давайте зв’яжемо це з IEnumerables
Численні - це лише колекція пасажирів на літаку. Закон про цивільну авіацію - це, в основному, правила, яких повинні дотримуватися всі ІМН. Кожен раз, коли супроводжувач авіакомпанії прямує до капітана з інформацією про пасажирів, ми, як правило, «піддаємо» пасажира капітану. Капітан може в основному робити все, що хоче, з пасажиром - крім перестановки пасажирів у літаку. У цьому випадку їм надається пільговий режим, якщо вони дотримуються Манчестер Сіті (так!)
foreach (Passenger passenger in Plane)
// the airline hostess is now at the front of the plane
// and slowly making her way towards the back
// when she get to a particular passenger she gets some information
// about the passenger and then immediately heads to the cabin
// to let the captain decide what to do with it
{ // <---------- Note the curly bracket that is here.
// we are now cockpit of the plane with the captain.
// the captain wants to give the passenger free
// champaign if they support manchester city
if (passenger.supports_mancestercity())
{
passenger.getFreeChampaign();
} else
{
// you get nothing! GOOD DAY SIR!
}
} // <---- Note the curly bracket that is here!
the hostess has delivered the information
to the captain and goes to the next person
on the plane (if she has not reached the
end of the plane)
Підсумок
Іншими словами, щось можна підрахувати, якщо у нього є лічильник . І лічильник повинен (в основному): (i) запам'ятати своє місце ( стан ), (ii) бути в змозі рухатися далі , (iii) і знати про поточну особу, з якою він має справу.
Численні - це просто фантазійне слово для "підрахунку". Іншими словами, число дозволяє вам «перерахувати» (тобто підрахувати).
IEnumerable реалізує GetEnumerator. При виклику цей метод поверне IEnumerator, який реалізує MoveNext, Reset та Current.
Таким чином, коли ваш клас реалізує IEnumerable, ви говорите, що ви можете викликати метод (GetEnumerator) і отримати новий повернутий об'єкт (IEnumerator), який ви можете використовувати в циклі, такому як foreach.
Реалізація IEnumerable дозволяє отримати список IEnumerator для списку.
IEnumerator дозволяє послідовно отримувати доступ до елементів у списку в стилі foreach, використовуючи ключове слово.
Перед реалізацією передбачення (наприклад, у Java 1.4) спосіб ітерації списку полягав у тому, щоб отримати перелік із списку, а потім задати йому пункт «наступний» у списку, доки значення повернеться як наступне елемент не є нульовим. Foreach просто робить це неявно, як мовна функція, так само, як lock () реалізує клас Monitor за кадром.
Я сподіваюся, що foreach працює за списками, оскільки вони реалізують IEnumerable.
Подумайте про численні об’єкти, як про списки, стеки, дерева.
IEnumerable та IEnumerator (та їх загальні аналоги IEnumerable <T> та IEnumerator <T>) є базовими інтерфейсами реалізації ітераторів у колекціях бібліотек .Net Framework Class .
IEnumerable - це найпоширеніший інтерфейс, який ви бачите в більшості кодів. Це дозволяє включати цикл foreach, генератори (думка про вихід ) і завдяки своєму крихітному інтерфейсу використовується для створення жорстких абстракцій. IEnumerable залежить від IEnumerator .
IEnumerator , з іншого боку, забезпечує трохи нижчий рівень інтерфейсу ітерації. Це називається явним ітератором, який дає програмісту більше контролю над циклом ітерації.
IEnumerable - це стандартний інтерфейс, який дозволяє повторювати колекції, які його підтримують (насправді всі типи колекцій, про які я сьогодні думаю, реалізують IEnumerable ). Підтримка компілятора дозволяє використовувати такі мовні функції foreach
. Загалом, це дозволяє це неявна реалізація ітератора .
foreach (var value in list)
Console.WriteLine(value);
Я думаю, що foreach
цикл є однією з головних причин використання інтерфейсів IEnumerable . foreach
має дуже лаконічний синтаксис і його дуже легко зрозуміти порівняно з класичним стилем C для циклів, де вам потрібно перевірити різні змінні, щоб побачити, що це робило.
Можливо, менш відома особливість полягає в тому, що IEnumerable також дозволяє генераторам в C # за допомогою yield return
і yield break
операторів.
IEnumerable<Thing> GetThings() {
if (isNotReady) yield break;
while (thereIsMore)
yield return GetOneMoreThing();
}
Іншим поширеним сценарієм на практиці є використання IEnumerable для надання мінімалістичних абстракцій. Оскільки це інтерфейс, призначений лише для прочитання та лише для читання, вам пропонується виставити свої колекції як IEnumerable (а не Список, наприклад). Таким чином, ви можете змінити свою реалізацію, не порушуючи код клієнта (змінити, наприклад, Список на LinkedList ).
Слід пам’ятати про те, що в потокових реалізаціях (наприклад, завантаження даних за рядком у базу даних, замість того, щоб спочатку завантажувати всі результати в пам'ять), ви не можете повторювати колекцію не один раз. Це на відміну від колекцій у пам'яті, таких як List , де ви можете повторити кілька разів без проблем. Наприклад, ReSharper має перевірку коду для можливого багаторазового перерахування IEnumerable .
З іншого боку, IEnumerator - це інтерфейс поза кадром, який робить магічну роботу IEnumerble-foreach . Власне кажучи, це дозволяє явні ітератори.
var iter = list.GetEnumerator();
while (iter.MoveNext())
Console.WriteLine(iter.Current);
На моєму досвіді IEnumerator рідко використовується в загальних сценаріях через його більш багатослівний синтаксис і трохи заплутану семантику (принаймні для мене; наприклад, MoveNext () також повертає значення, яке назва зовсім не підказує).
Я використовував тільки IEnumerator, зокрема (трохи нижчий рівень) бібліотек та фреймворків, де я забезпечував інтерфейси IEnumerable . Одним із прикладів є бібліотека обробки потоків даних, яка надає низку об'єктів у foreach
циклі, навіть якщо за кадром дані збираються за допомогою різних потоків файлів та серіалізації.
Код клієнта
foreach(var item in feed.GetItems())
Console.WriteLine(item);
Бібліотека
IEnumerable GetItems() {
return new FeedIterator(_fileNames)
}
class FeedIterator: IEnumerable {
IEnumerator GetEnumerator() {
return new FeedExplicitIterator(_stream);
}
}
class FeedExplicitIterator: IEnumerator {
DataItem _current;
bool MoveNext() {
_current = ReadMoreFromStream();
return _current != null;
}
DataItem Current() {
return _current;
}
}
Реалізація IEnumerable
по суті означає, що об'єкт може бути повторений. Це не обов'язково означає, що це масив, оскільки є певні списки, які не можна індексувати, але ви можете їх перерахувати.
IEnumerator
- це власне об'єкт, який використовується для виконання ітерацій. Він контролює переміщення від одного об’єкта до іншого в списку.
Більшість випадків IEnumerable
& IEnumerator
використовуються прозоро як частина foreach
циклу.
Відмінності між IEnumerable та IEnumerator:
Кожного разу, коли ми передаємо колекцію IEnumerable до іншої функції, вона не знає поточного положення елемента / об'єкта (не знає, який елемент виконує)
IEnumerable мають один метод GetEnumerator ()
public interface IEnumerable<out T> : IEnumerable { IEnumerator<T> GetEnumerator(); }
IEnumerator має одне властивість під назвою Current та два методи Reset () та MoveNext () (що корисно для того, щоб знати поточну позицію елемента в списку).
public interface IEnumerator
{
object Current { get; }
bool MoveNext();
void Reset();
}
IEnumerable - це вікно, яке містить Ienumerator. IEnumerable є базовим інтерфейсом для всіх колекцій. цикл foreach може працювати, якщо колекція реалізує IEnumerable. У наведеному нижче коді пояснюється крок створення власного перелік. Давайте спочатку визначимо наш клас, з якого ми збираємось скласти колекцію.
public class Customer
{
public String Name { get; set; }
public String City { get; set; }
public long Mobile { get; set; }
public double Amount { get; set; }
}
Тепер ми визначимо клас, який буде виступати як колекція для нашого класу. Зауважте, що він реалізує інтерфейс IEnumerable. Так що нам доведеться реалізувати метод GetEnumerator. Це поверне наш користувальницький перелік.
public class CustomerList : IEnumerable
{
Customer[] customers = new Customer[4];
public CustomerList()
{
customers[0] = new Customer { Name = "Bijay Thapa", City = "LA", Mobile = 9841639665, Amount = 89.45 };
customers[1] = new Customer { Name = "Jack", City = "NYC", Mobile = 9175869002, Amount = 426.00 };
customers[2] = new Customer { Name = "Anil min", City = "Kathmandu", Mobile = 9173694005, Amount = 5896.20 };
customers[3] = new Customer { Name = "Jim sin", City = "Delhi", Mobile = 64214556002, Amount = 596.20 };
}
public int Count()
{
return customers.Count();
}
public Customer this[int index]
{
get
{
return customers[index];
}
}
public IEnumerator GetEnumerator()
{
return customers.GetEnumerator(); // we can do this but we are going to make our own Enumerator
return new CustomerEnumerator(this);
}
}
Тепер ми збираємось створити власний власний Enumerator, як описано нижче. Отже, ми повинні реалізувати метод MoveNext.
public class CustomerEnumerator : IEnumerator
{
CustomerList coll;
Customer CurrentCustomer;
int currentIndex;
public CustomerEnumerator(CustomerList customerList)
{
coll = customerList;
currentIndex = -1;
}
public object Current => CurrentCustomer;
public bool MoveNext()
{
if ((currentIndex++) >= coll.Count() - 1)
return false;
else
CurrentCustomer = coll[currentIndex];
return true;
}
public void Reset()
{
// we dont have to implement this method.
}
}
Тепер ми можемо використовувати цикл foreach над нашою колекцією, як нижче;
class EnumeratorExample
{
static void Main(String[] args)
{
CustomerList custList = new CustomerList();
foreach (Customer cust in custList)
{
Console.WriteLine("Customer Name:"+cust.Name + " City Name:" + cust.City + " Mobile Number:" + cust.Amount);
}
Console.Read();
}
}
Розуміння структури Ітератора буде для вас корисним. Я рекомендую прочитати те саме.
На високому рівні схему ітератора можна використовувати для забезпечення стандартного способу ітерації за допомогою колекцій будь-якого типу. У нас є 3 учасники в ітераторному шаблоні, фактична колекція (клієнт), агрегатор та ітератор. Сукупність - це інтерфейс / абстрактний клас, який має метод, який повертає ітератор. Ітератор - це інтерфейс / абстрактний клас, який має методи, що дозволяють нам переглядати колекцію.
Для реалізації шаблону нам спочатку потрібно здійснити ітератор для отримання бетону, який може перебирати відповідну колекцію (клієнта). Потім колекція (клієнт) реалізує агрегатор, щоб повернути екземпляр зазначеного вище ітератора.
Таким чином, в основному в c #, IEnumerable є абстрактним агрегатом, а IEnumerator - абстрактним ітератором. IEnumerable має єдиний метод GetEnumerator, який відповідає за створення екземпляра IEnumerator потрібного типу. Колекції, такі як Списки, реалізують IEnumerable.
Приклад. Припустимо, що у нас є метод, getPermutations(inputString)
який повертає всі перестановки рядка і що метод повертає екземплярIEnumerable<string>
Для того, щоб підрахувати кількість перестановок, ми могли б зробити щось подібне нижче.
int count = 0;
var permutations = perm.getPermutations(inputString);
foreach (string permutation in permutations)
{
count++;
}
Компілятор c # більш-менш перетворює вищезазначене в
using (var permutationIterator = perm.getPermutations(input).GetEnumerator())
{
while (permutationIterator.MoveNext())
{
count++;
}
}
Якщо у вас є якісь питання, будь ласка, не соромтеся їх задавати.
Незначний внесок.
Оскільки багато хто з них пояснюють питання про те, «коли використовувати» та «використовувати з foreach». Я думав додати сюди ще одну різницю станів, як запитували питання про різницю між обома IEnumerable IEnumerator.
Я створив нижченаведений зразок коду на основі нижче обговорених тем.
IEnumerable, IEnumerator vs foreach, коли використовувати Яка різниця між IEnumerator та IEnumerable?
Керівник зберігає стан (позицію ітерації) між викликами функцій, тоді як ітерації, з іншого боку, перераховують.
Ось тестований приклад з коментарями, щоб зрозуміти.
Фахівці, будь ласка, додайте / виправте мене.
static void EnumerableVsEnumeratorStateTest()
{
IList<int> numList = new List<int>();
numList.Add(1);
numList.Add(2);
numList.Add(3);
numList.Add(4);
numList.Add(5);
numList.Add(6);
Console.WriteLine("Using Enumerator - Remembers the state");
IterateFrom1to3(numList.GetEnumerator());
Console.WriteLine("Using Enumerable - Does not Remembers the state");
IterateFrom1to3Eb(numList);
Console.WriteLine("Using Enumerable - 2nd functions start from the item 1 in the collection");
}
static void IterateFrom1to3(IEnumerator<int> numColl)
{
while (numColl.MoveNext())
{
Console.WriteLine(numColl.Current.ToString());
if (numColl.Current > 3)
{
// This method called 3 times for 3 items (4,5,6) in the collection.
// It remembers the state and displays the continued values.
IterateFrom3to6(numColl);
}
}
}
static void IterateFrom3to6(IEnumerator<int> numColl)
{
while (numColl.MoveNext())
{
Console.WriteLine(numColl.Current.ToString());
}
}
static void IterateFrom1to3Eb(IEnumerable<int> numColl)
{
foreach (int num in numColl)
{
Console.WriteLine(num.ToString());
if (num>= 5)
{
// The below method invokes for the last 2 items.
//Since it doesnot persists the state it will displays entire collection 2 times.
IterateFrom3to6Eb(numColl);
}
}
}
static void IterateFrom3to6Eb(IEnumerable<int> numColl)
{
Console.WriteLine();
foreach (int num in numColl)
{
Console.WriteLine(num.ToString());
}
}
Я помітив ці відмінності:
A. Ми повторюємо список по-різному, foreach може використовуватися для IEnumerable і while цикл для IEnumerator.
B. IEnumerator може запам'ятати поточний індекс, коли ми переходимо від одного методу до іншого (він починає працювати з поточним індексом), але IEnumerable не може запам'ятати індекс і він скидає індекс до початку. Детальніше у цьому відео https://www.youtube.com/watch?v=jd3yUjGc9M0
IEnumerable
і IEnumerator
обидва є інтерфейсами в C #.
IEnumerable
це інтерфейс, що визначає єдиний метод, GetEnumerator()
який повертає IEnumerator
інтерфейс.
Це працює для доступу лише до читання до колекції, яка реалізує, яку IEnumerable
можна використовувати з foreach
оператором.
IEnumerator
має два способи, MoveNext
і Reset
. Він також має властивість під назвою Current
.
Далі показано реалізацію IEnumerable та IEnumerator.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Enudemo
{
class Person
{
string name = "";
int roll;
public Person(string name, int roll)
{
this.name = name;
this.roll = roll;
}
public override string ToString()
{
return string.Format("Name : " + name + "\t Roll : " + roll);
}
}
class Demo : IEnumerable
{
ArrayList list1 = new ArrayList();
public Demo()
{
list1.Add(new Person("Shahriar", 332));
list1.Add(new Person("Sujon", 333));
list1.Add(new Person("Sumona", 334));
list1.Add(new Person("Shakil", 335));
list1.Add(new Person("Shruti", 336));
}
IEnumerator IEnumerable.GetEnumerator()
{
return list1.GetEnumerator();
}
}
class Program
{
static void Main(string[] args)
{
Demo d = new Demo(); // Notice here. it is simple object but for
//IEnumerator you can get the collection data
foreach (Person X in d)
{
Console.WriteLine(X);
}
Console.ReadKey();
}
}
}
/*
Output :
Name : Shahriar Roll : 332
Name : Sujon Roll : 333
Name : Sumona Roll : 334
Name : Shakil Roll : 335
Name : Shruti Roll : 336
*/