تنفيذ العداد ثنائي الاتجاه في C #
-
19-08-2019 - |
سؤال
هل هناك طريقة لاستخدام كتل العائد لتنفيذ IEnumerator<T>
التي يمكن العودة إلى الوراء (MoveLast()
)، وكذلك إلى الأمام؟
المحلول
وليس مباشرة من كتلة مكرر، لا.
ومع ذلك، فإن المتصل يمكن العازلة دائما النتائج، على سبيل المثال في List<T>
، أو مجرد دعوة Reverse()
- ولكن هذا لا ينطبق دائما
نصائح أخرى
لا، آلة الدولة التي تم إنشاؤها بواسطة C # مترجم بشكل صارم إلى الأمام.
وبل لا معنى للذهاب الى الوراء في كثير من الحالات. تخيل مكرر القراءة من تيار الشبكة - للذهاب الى الوراء، فإنه سيتعين عليها أن تتذكر كل شيء أنه قد قرأ من أي وقت مضى، لأنه لا يمكن إرجاع الوقت ومطالبة الشبكة للبيانات مرة أخرى
.و(كما سبق أي شيء التي ولدت البيانات في بعض الطريق الضياع تخيل مكرر التي عادت مجلس إدارة جديد للحياة كونواي على كل التكرار - هناك لوحات متعددة والتي يمكن أن يكون جميع <م> سابقة م> واحد، لذلك لنعود إلى الوراء لديك مرة أخرى لتذكر ما كنت قد عادوا بالفعل).
وأنا أعرف هذا الموضوع هو السوبر القديم ولكن من المناسب الإشارة إلى أن
foreach(var item in someCollection)
{
// Do something
}
... والحصول على تجميعها في:
var enumerator = someCollection.GetEnumerator()
while (enumerator.MoveNext())
{
var item = enumerator.Current;
// Do something
}
وحتى إذا كنت لا تمانع في بناء الجملة "MOVENEXT"، يمكن بسهولة تنفيذ IEnumerator وإضافة "MovePrevious". أنت لن تكون قادرة على عكس الاتجاه إذا كنت تستخدم "foreach" ولكنك تريد ان تكون قادرة على عكس الاتجاه في حالة استخدام حلقة while.
وأو ... إذا كنت ترغب في "foreach" قائمة في الاتجاه المعاكس (لا ثنائية الاتجاه) هل يمكن الاستفادة من العائد بيان.
public static IEnumerable<TItem> Get<TItem>(IList<TItem> list)
{
if (list == null)
yield break;
for (int i = list.Count - 1; i > -1; i--)
yield return list[i];
}
وأو ... إذا كنت تريد أن foreach في الاتجاه المعاكس من خلال تسير في الطريق الطويل يمكنك تطبيق بنفسك IEnumerable / IEnumerator
public static class ReverseEnumerable
{
public static IEnumerable<TItem> Get<TItem>(IList<TItem> list)
{
return new ReverseEnumerable<TItem>(list);
}
}
public struct ReverseEnumerable<TItem> : IEnumerable<TItem>
{
private readonly IList<TItem> _list;
public ReverseEnumerable(IList<TItem> list)
{
this._list = list;
}
public IEnumerator<TItem> GetEnumerator()
{
if (this._list == null)
return Enumerable.Empty<TItem>().GetEnumerator();
return new ReverseEnumator<TItem>(this._list);
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
public struct ReverseEnumator<TItem> : IEnumerator<TItem>
{
private readonly IList<TItem> _list;
private int _currentIndex;
public ReverseEnumator(IList<TItem> list)
{
this._currentIndex = list.Count;
this._list = list;
}
public bool MoveNext()
{
if (--this._currentIndex > -1)
return true;
return false;
}
public void Reset()
{
this._currentIndex = -1;
}
public void Dispose() { }
public TItem Current
{
get
{
if (this._currentIndex < 0)
return default(TItem);
if (this._currentIndex >= this._list.Count)
return default(TItem);
return this._list[this._currentIndex];
}
}
object IEnumerator.Current
{
get { return this.Current; }
}
}
ولا. واحدة من القيود المفروضة على IEnumerator هو أنه يحمل وضعها الحالي، وأنها لا تذكر حالته السابقة. ونتيجة لذلك، IEnumerable هو إلى الأمام فقط.
إذا كنت بحاجة إلى التمسك الدول السابقة، وقراءة IEnumerable إلى قائمة أو قائمة متصلة وتعداد من خلال تلك الأشياء بدلا من ذلك.
في الواقع، يبدو أن يكون هناك نهج وصفها في <لأ href = "http://books.google.com/books؟id=A-vzSC3zhqMC&pg=PA247&lpg=PA247&dq=bidirectional+enumerator+c٪23&source=bl&ots= kdZFYaHmIM وسيج = rBeEPLRXvoa-JyfZ3lmbCMBEQrg وHL = EN & سا = X & منظمة اوكسفام الدولية = book_result وresnum = 2 & ط = نتيجة # PPA249، M1 "يختلط =" نوفولو noreferrer "> المعجل C # 2008 . للأسف، صفحتين تكون غير مرئية في المعاينة، ولها أن تعتمد على تفكير (والنتائج التي يمكن أن يكون مؤقتا، كالعادة) ولكن يمكنك الحصول على جوهر.
ولا. باستخدام yield
النتائج في <لأ href = "HTTP: // msdn.microsoft.com/en-us/library/9k7k7cf0.aspx "يختلط =" نوفولو noreferrer "> IEnumerable
وهو أحادي الاتجاه.