C# list.Take(100.ToList()与list.GetRange(0100)的比较 列出与会者=新建列表(); foreach。。。 //错误:“电子邮件地址数组中的目标用户太多” //超过100名与会者。因此,仅以前100名与会者为例。 如果(Attendes.Count>100)Attendes=Attendes.GetRange(0100); //或 如果(Attendes.Count>100)Attendes=Attendes.Take(100.ToList();

C# list.Take(100.ToList()与list.GetRange(0100)的比较 列出与会者=新建列表(); foreach。。。 //错误:“电子邮件地址数组中的目标用户太多” //超过100名与会者。因此,仅以前100名与会者为例。 如果(Attendes.Count>100)Attendes=Attendes.GetRange(0100); //或 如果(Attendes.Count>100)Attendes=Attendes.Take(100.ToList();,c#,linq,C#,Linq,因为我的列表总是超过100个,而且总是取前100个,所以最明显的差异(评估策略、跳过的可能性、出错的可能性)并不是很有趣 但也许您可以解释一下“在源代码列表中创建一系列元素的浅拷贝”的确切含义。它听起来确实很昂贵,比Take更贵,是吗?唯一的区别是它比Take(n).ToList()更高效,因为它已经知道新列表的大小,而LINQ方法不知道它的大小 因此,枚举序列并使用双倍算法将项目添加到一个新列表中,并连续增加支持数组列表。GetRange可以预先创建具有正确初始大小的适当列表,然后使用它将源列

因为我的列表总是超过100个,而且总是取前100个,所以最明显的差异(评估策略、跳过的可能性、出错的可能性)并不是很有趣


但也许您可以解释一下“在源代码列表中创建一系列元素的浅拷贝”的确切含义。它听起来确实很昂贵,比Take更贵,是吗?

唯一的区别是它比
Take(n).ToList()
更高效,因为它已经知道新列表的大小,而LINQ方法不知道它的大小

因此,枚举序列并使用双倍算法将项目添加到一个新列表中,并连续增加支持数组<代码>列表。GetRange可以预先创建具有正确初始大小的适当列表,然后使用它将源列表的子集复制到新列表[]中。

以下是实现:

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();
此外,这只是:

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;
            }
        }
    }
}

您可以立即注意到,相比于
Take
GetRange
要便宜得多,它要快得多。看看这个:

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);
            }
        }
    }
}
var list=Enumerable.Range(0,1000).ToList();
var stopwatch=新秒表();
秒表。开始();
对于(var i=0;iList.Take(100).ToList(),如果您不知道列表中的元素数,则更合适。如果小于100,则只取可用的元素。使用此选项更灵活。

另一方面,List.GetRange(0100)假设列表中的元素数超过100。但是,您会得到此错误***

偏移量和长度超出了数组的界限或计数更大 大于从索引到源结尾的元素数 收藏

***。 如果元素数小于指定的范围


对我来说,List.Take(100).ToList()更一般,因为它不限制使用。

Take
GetRange
之间有一个微小的差别。Take将惰性地进行评估,直到你强迫它评估为
ToList()
。这会改变行为

考虑伪代码

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);
List myList=newlist(){1,2,3,4,5,6};
IEnumerable otherList=myList.Take(3);/{1,2,3};
myList.Removate(0,3);
//myList={4,5,6}
//otherList={4,5,6}
现在将此示例更改为以下代码

List<int> myList = new List<int>() {1,2,3,4,5,6};
IEnumerable<int> otherList = myList.Take(3);  // {1,2,3};
myList.RemoveRange(0,3);
// myList = {4, 5, 6}
// otherList = {4, 5, 6}
List myList=newlist(){1,2,3,4,5,6};
IEnumerable otherList=myList.Take(3.ToList();/{1,2,3};
myList.Removate(0,3);
//myList={4,5,6}
//otherList={1,2,3}
执行
ToList()
可以根据下一步使用的操作更改Take或GetRange的行为。使用GetRange总是比较容易,因为它不会导致任何未知错误


GetRange也是有效的。

您省略了核心功能
List
的构造函数。此外,如果您只计算代码行,方法的效率也不明显。我知道您在示例中使用了列表,但需要注意的是,如果您使用的是数组,您可以执行以下操作:
int[]source={1,2,3,4,5,6};IList Attendeers=new ArraySegment(source,2,source.Length-2);
它只是在数组周围创建一个轻包装,跳过前n个(本例中为2个)元素。
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);
List<int> myList = new List<int>() {1,2,3,4,5,6};
IEnumerable<int> otherList = myList.Take(3);  // {1,2,3};
myList.RemoveRange(0,3);
// myList = {4, 5, 6}
// otherList = {4, 5, 6}
List<int> myList = new List<int>() {1,2,3,4,5,6};
IEnumerable<int> otherList = myList.Take(3).ToList();  // {1,2,3};
myList.RemoveRange(0,3);
// myList = {4, 5, 6}
// otherList = {1, 2, 3}