मैंने अभी भी Skip
/Take
.NET Framework (IEnumerable<T>
प्रकार) के विस्तार विधियों के स्रोत कोड पर एक नज़र डाली और पाया कि आंतरिक कार्यान्वयन के साथ काम कर रहा है GetEnumerator
विधि:छोड़ने का प्रदर्शन (और इसी तरह के कार्यों, जैसे टेक)
// .NET framework
public static IEnumerable<TSource> Skip<TSource>(this IEnumerable<TSource> source, int count)
{
if (source == null) throw Error.ArgumentNull("source");
return SkipIterator<TSource>(source, count);
}
static IEnumerable<TSource> SkipIterator<TSource>(IEnumerable<TSource> source, int count)
{
using (IEnumerator<TSource> e = source.GetEnumerator())
{
while (count > 0 && e.MoveNext()) count--;
if (count <= 0)
{
while (e.MoveNext()) yield return e.Current;
}
}
}
मान लीजिए कि मैं एक IEnumerable<T>
1000 तत्वों (अंतर्निहित प्रकार List<T>
है) है। अगर मैं सूची कर रहा हूं तो क्या होगा। स्किप (9 0 9)। टेक (10)? क्या यह अंतिम दस लेने से पहले 9 0 9 के पहले तत्वों को थकाऊ करेगा? (इस तरह मैं इसे समझता हूं)। यदि हाँ, तो मुझे समझ नहीं आता क्यों माइक्रोसॉफ्ट Skip
विधि इस तरह लागू नहीं किया:
// Not tested... just to show the idea
public static IEnumerable<T> Skip<T>(this IEnumerable<T> source, int count)
{
if (source is IList<T>)
{
IList<T> list = (IList<T>)source;
for (int i = count; i < list.Count; i++)
{
yield return list[i];
}
}
else if (source is IList)
{
IList list = (IList)source;
for (int i = count; i < list.Count; i++)
{
yield return (T)list[i];
}
}
else
{
// .NET framework
using (IEnumerator<T> e = source.GetEnumerator())
{
while (count > 0 && e.MoveNext()) count--;
if (count <= 0)
{
while (e.MoveNext()) yield return e.Current;
}
}
}
}
वास्तव में, वे किया था कि उदाहरण के लिए Count
विधि ... के लिए
// .NET Framework...
public static int Count<TSource>(this IEnumerable<TSource> source)
{
if (source == null) throw Error.ArgumentNull("source");
ICollection<TSource> collectionoft = source as ICollection<TSource>;
if (collectionoft != null) return collectionoft.Count;
ICollection collection = source as ICollection;
if (collection != null) return collection.Count;
int count = 0;
using (IEnumerator<TSource> e = source.GetEnumerator())
{
checked
{
while (e.MoveNext()) count++;
}
}
return count;
}
तो क्या कारण है?
मुझे पता चला है कि यह मानना हमेशा सर्वोत्तम होता है कि उन विधियों को कभी अनुकूलित नहीं किया जाता है।यहां तक कि गणना() के लिए, यह 'ICollection <>' के लिए अनुकूलित करता है, लेकिन 'IReadOnlyCollection <>' नहीं। यदि आपको इसे अनुकूलित करने की आवश्यकता है, तो अपना खुद का लिखें। – RobSiklos
क्योंकि उन्होंने उस अनुकूलन को जोड़ने के लिए कभी भी परेशान नहीं किया? अगर आपको लगता है कि इससे मदद मिलती है तो मुझे आपके साथ ऐसा कोई समस्या नहीं दिखती है। लेकिन ध्यान दें कि फिर 'myList.Select (..)। छोड़ें (100) 'myList.Skip (100) से धीमा है। चयन करें (..)', भले ही वे कार्यात्मक रूप से वही हों। –
यह भी ध्यान दें कि लिंक-टू-एसक्यूएल और ईएफ 'छोड़ें' और 'टेक' में एसक्यूएल क्वेरी में धक्का दिया जाता है, इसलिए यह पूर्व वस्तुओं के माध्यम से पुनरावृत्ति नहीं करता है। (_SQL_ एक टेबल/इंडेक्स स्कैन के माध्यम से हो सकता है, लेकिन लिंक नहीं करता है) –