List.Take (100) .ToList () vs. list.GetRange (0,100)

List<AttendeeInfo> attendees = new List<AttendeeInfo>(); foreach ... // Error: "There are too many target users in the email address array" // for more than 100 attendees. So take the first 100 attendees only. if(attendees.Count > 100) attendees = attendees.GetRange(0,100); // or if(attendees.Count > 100) attendees = attendees.Take(100).ToList(); 

Since I am working on a list that is always longer than 100, and always take the first 100, the most obvious differences (evaluation strategy, the ability to skip, throw errors) are not really interesting.

But perhaps you could shed some light on what exactly means "Creates a shallow copy of the range of elements in the source list." It sounds very expensive, more than Take, but does it?

+5
source share
4 answers

The only difference is that List.GetRange more efficient than Take(n).ToList() because it already knows the size of the new list, while LINQ methods don't know its size.

So ToList enumerates the sequence and adds items to the new list with a doubling algorithm that sequentially increases the lookup array. List.GetRange can create the correct list with the correct initial size in advance, and then use Array.Copy to copy a subset of the original list to the new [ source ] list.

+13
source

It is much faster. Check this:

 var list = Enumerable.Range(0, 1000).ToList(); var stopwatch = new Stopwatch(); stopwatch.Start(); for(var i=0; i<1000000; i++) { var c = list.GetRange(0, 100); } Console.WriteLine(stopwatch.Elapsed); stopwatch.Restart(); for (var i = 0; i < 1000000; i++) { var c = list.Take(100).ToList(); } Console.WriteLine(stopwatch.Elapsed); 

Elapsed Time:

List.GetRange() : 0.149 s

List.Take().ToList() : 3.625 s

+4
source

Here is the GetRange :

 public List<T> GetRange(int index, int count) { if (index < 0) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); } if (count < 0) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); } if ((this._size - index) < count) { ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); } List<T> list = new List<T>(count); Array.Copy(this._items, index, list._items, 0, count); // Implemented natively list._size = count; return list; } 

And this is Take Implementation

 public static IEnumerable<TSource> Take<TSource>(this IEnumerable<TSource> source, int count) { if (source == null) { throw Error.ArgumentNull("source"); } return TakeIterator<TSource>(source, count); } private static IEnumerable<TSource> TakeIterator<TSource>(IEnumerable<TSource> source, int count) { if (count > 0) { foreach (TSource iteratorVariable0 in source) { yield return iteratorVariable0; if (--count == 0) { break; } } } } 

Plus a ToList that just does:

 public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) { if (source == null) { throw Error.ArgumentNull("source"); } return new List<TSource>(source); } 

And the List constructor:

 public List(IEnumerable<T> collection) { if (collection == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); } ICollection<T> is2 = collection as ICollection<T>; if (is2 != null) { int count = is2.Count; if (count == 0) { this._items = List<T>._emptyArray; } else { this._items = new T[count]; is2.CopyTo(this._items, 0); this._size = count; } } else { this._size = 0; this._items = List<T>._emptyArray; using (IEnumerator<T> enumerator = collection.GetEnumerator()) { while (enumerator.MoveNext()) { this.Add(enumerator.Current); } } } } 

You can immediately notice how GetRange cheaper GetRange Take

+2
source

List.Take (100) .ToList () , it would be more appropriate if you do not know the number of elements in the list. If it is less than 100, it will simply be available. more flexible to use it.

On the other hand, List.GetRange (0,100) assumes that the number of elements in the list is more than 100. However, you will get this error ***

The offset and length were outside the bounds of the array or the number was greater than the number of elements from the index to the end of the source. Collection

*** if the number of elements is less than the specified range.

For me, I would say that List.Take (100) .ToList () is more generic because it does not restrict use.

0
source

Source: https://habr.com/ru/post/1231928/


All Articles