27

获取原语列表并将其转换为可为空的原语列表的最快方法是什么?例如:List<int>List<int?>

简单的解决方案是创建一个新列表并使用foreach循环添加每个项目,这需要太多时间。

4

4 回答 4

58

没有比创建新列表更快的方法了:

var newList = list.Select( i => (int?)i ).ToList();

但是,使用 LINQ 比使用裸循环要慢。

最快的方法是使用List<int?>具有预分配容量的 a:

List<int?> newList = new List<int?>(list.Count); // Allocate enough memory for all items
foreach (var i in list)
    newList.Add(i);

如果您正在寻找列表项的就地类型更改,这是不可能的。

于 2013-03-03T10:11:54.183 回答
16

而不是Select你可以坚持使用CastLINQ 运算符:

List<int> first = new List<int>() {1, 2, 3};
List<int?> second = first.Cast<int?>().ToList();
于 2013-03-03T10:27:41.000 回答
7

如果您想知道更快的解决方案是什么,您应该使用三种不同的方式做一个小基准测试:

List<int> list = Enumerable.Range( 0, 10000 ).ToList( );
Stopwatch sw = Stopwatch.StartNew( );

for ( int i = 0; i < 100000; i++ ) {
   List<int?> newList = new List<int?>( );
   foreach( int integer in list )
      newList.Add( ( int? ) integer );
}

sw.Stop( );
TimeSpan timespan = sw.Elapsed;
Console.WriteLine( String.Format( "Foreach: {0:00}:{1:00}:{2:00}", timespan.Minutes, timespan.Seconds, timespan.Milliseconds / 10 ) );
sw.Restart( );

for ( int i = 0; i < 100000; i++ ){
   List<int?> newList = list.Select( x => ( int? ) x ).ToList( );
}

sw.Stop( );
timespan = sw.Elapsed;
Console.WriteLine( String.Format( "LINQ-Select: {0:00}:{1:00}:{2:00}", timespan.Minutes, timespan.Seconds, timespan.Milliseconds / 10 ) );
sw.Restart( );

for ( int i = 0; i < 100000; i++ ){
   List<int?> newList = list.Cast<int?>( ).ToList( );
}

sw.Stop();
timespan = sw.Elapsed;
Console.WriteLine( String.Format( "LINQ-Cast: {0:00}:{1:00}:{2:00}", timespan.Minutes, timespan.Seconds, timespan.Milliseconds / 10 ) );

结果:

基准

正如我们所料,最好的方法是第一个解决方案 ( foreach),这意味着循环遍历元素,强制转换并将它们添加到新列表中。

于 2013-03-03T11:10:22.497 回答
0

这不是一个新问题,但我目前使用此代码;我分享它,希望它可以帮助其他有同样问题的人: List with pre-allocated + Linq

var branchIds = new List<int?>(branches.Count);
branchIds.AddRange(branches.Select(int.Parse).Select(brId => (int?)brId));
于 2018-01-13T13:29:40.907 回答