很遗憾,你不能。来自语言规范:
例如,以下 .NET 类型同时支持索引和范围:String、Span 和 ReadOnlySpan。 List 支持索引,但不支持范围。
Type Support for ranges and indices.
所以唯一的方法就是这样,有点笨拙:
var subList = list.ToArray()[0..1];
编辑:我将把我的其余答案留作记录,但我认为使用Range 的答案更优雅,并且会明显更快,尤其是对于大切片。
基准和扩展方法
下面演示了使用ToArray() 可以减慢多少(使用 LINQPad - F.Rnd.Str 是我自己生成随机字符串的辅助方法):
var list = new List<string>();
for (int i = 0; i < 100000; i++)
{
list.Add(F.Rnd.Str);
}
// Using ToArray()
var timer = new Stopwatch();
timer.Start();
var subList0 = list.ToArray()[42..142];
timer.Stop();
timer.ElapsedTicks.Dump("ToArray()");
// Using Indices
timer.Reset();
timer.Start();
var subList1 = new List<string>();
for (int i = 42; i < 142; i++)
{
subList1.Add(list[i]);
}
timer.Stop();
timer.ElapsedTicks.Dump("Index");
// ToArray()
// 3136
// Index
// 28
因此,这样的扩展方法会很快:
public static class ListExtensions
{
public static List<T> GetSlice<T>(this List<T> @this, int first, int last)
{
var slice = new List<T>();
for (int i = first; i < last; i++)
{
slice.Add(@this[i]);
}
return slice;
}
}
然后您可以将其添加到基准测试中:
// Using Extension Method
timer.Reset();
timer.Start();
var subList2 = list.GetSlice(42, 142);
timer.Stop();
timer.ElapsedTicks.Dump("Extension");
基准测试结果:
// ToArray()
// 2021
// Index
// 16
// Extension
// 15
范围
其中一个答案使用Range 来实现相同的目的,所以为了比较:
timer.Reset();
timer.Start();
var range = new Range(42, 142);
var (start, length) = range.GetOffsetAndLength(list.Count);
var subList3 = list.GetRange(start, length);
timer.Stop();
timer.ElapsedTicks.Dump("Range");
基准测试结果:
// ToArray()
// 2056
// Index
// 21
// Extension
// 16
// Range
// 17
您可以看到底部三种方法在速度方面基本相同(因为我多次运行它,它们都在 15-21 滴答之间变化)。