PDA

View Full Version : سوال در مورد IEnumerable



خسرو خان
شنبه 24 تیر 1391, 09:39 صبح
با سلام

میخواستم بدونم
IEnumerable
چیه و به چه دردی می خوره و کجاها استفاده میشه ؟

ممنون

tooraj_azizi_1035
شنبه 24 تیر 1391, 11:28 صبح
سلام
این اینترفیس باعث میشه روی یک کلکسیون که این اینترفیس رو پیاده می کنه عمل iteration یا مرور عناصر دورن کلکسیون رو انجام داد.
دارای یک عضو به نام GetEnumerator است که خود GetEnumerator که نوع بازگشتی اش یک اینترفیس IEnumerator است دارای سه عضو است:
Reset، Current، MoveNext.

با استفاده از دستور Foreach عمل مرور عناصر انجام میشه اما اجازه اعمال تغییر در کلکسیون (کم یا زیاد کردن عناصر) را نخواهیم داشت. Enumerator در ابتدا به قبل از اولین عنصر اشاره دارد. متد Reset باعث می شود که اشاره گر عنصر جاری به این محل بازگردد.در این موقعیت خصوصیت Current تعریف نشده است. بنابراین شما می بایست متد MoveNext را صدا بزنید تا اشاره گر یکی به جلو حرکت داده شود قبل از اینکه عنصر جاری خوانده شود.

اگر MoveNext به انتهای کلکسیون رسیده باشد در این صورت اشاره گر به بعد از آخرین عنصر اشاره می کند و MoveNext مقدار false بر می گرداند.

یک Enumerator تا زمانی معتبر است که کلکسیون دست نخورده باقی بماند. اگر هر گونه تغییری اعم از حذف، اضافه و تغییر صورت بگیرد رفتار Enumerator قابل پیش بینی نخواهد بود.

Enumerator دسترسی انحصاری به کلکسیون ندارد بلکه نخ های اجرایی دیگر هم می توانند همزمان به کلکسیون دست داشته باشند بنابراین برای اعمال Thread-Safety می توانید از مکانیزم lock در طول عمل مرور عناصر استفاده نمائید.



مثال:


using System;
using System.Collections;

public class Person
{
public Person(string fName, string lName)
{
this.firstName = fName;
this.lastName = lName;
}

public string firstName;
public string lastName;
}

public class People : IEnumerable
{
private Person[] _people;
public People(Person[] pArray)
{
_people = new Person[pArray.Length];

for (int i = 0; i < pArray.Length; i++)
{
_people[i] = pArray[i];
}
}

IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator) GetEnumerator();
}

public PeopleEnum GetEnumerator()
{
return new PeopleEnum(_people);
}
}

public class PeopleEnum : IEnumerator
{
public Person[] _people;

// Enumerators are positioned before the first element
// until the first MoveNext() call.
int position = -1;

public PeopleEnum(Person[] list)
{
_people = list;
}

public bool MoveNext()
{
position++;
return (position < _people.Length);
}

public void Reset()
{
position = -1;
}

object IEnumerator.Current
{
get
{
return Current;
}
}

public Person Current
{
get
{
try
{
return _people[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
}

class App
{
static void Main()
{
Person[] peopleArray = new Person[3]
{
new Person("John", "Smith"),
new Person("Jim", "Johnson"),
new Person("Sue", "Rabon"),
};

People peopleList = new People(peopleArray);
foreach (Person p in peopleList)
Console.WriteLine(p.firstName + " " + p.lastName);

}
}

/* This code produces output similar to the following:
*
* John Smith
* Jim Johnson
* Sue Rabon
*
*/




کلاس Person، پیاده سازی خاص خودش از IEnumerable را دارد و اصطلاحاً یک کلاس را قابل شمارش کرده یعنی اگر کلکسیونی از اشیای Person داشته باشیم دستور foreach برای این کلکسیون ممکن می شود.

MoveNext و Reset و Current در Person رفتاری دارد که در کلاس های دیگر می تواند اینگونه نباشد گرچه عمل حرکت رو به جلو و برداشتن عنصر جاری یا Reset می تواند یک منطق در همه کلاس داشته باشد اما کد آن مطمئناً متفاوت خواهد بود.:قلب:

بیشتر: http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.getenumerator.aspx