What's the difference between select new VS fo

2019-09-26 08:06发布

问题:

Is there any difference between

 int i = 0;
 var myItems = (from source in datasource
                         select new MyObject
                         {
                             LabelId = i++,
                             Label = source.SourceName,
                             Data = source.TotalCount
                         }).ToList();

and

 int i = 0;
 List<MyObject> myItems = new List<MyObject>();
 foreach (var source in datasource)
        {
            MyObject myItem = new MyObject()
            {
                Label = item.SourceName,
                LabelId = i++,
                Data = item.TotalCount                
            };
            myItems.Add(myItem);
        }           

When dealing with performance / complexity time ?

回答1:

There are a few differences.

  1. The first is slightly clearer.

  2. For some data sources (Link to SQL is the classic example but any IQueryable datasource may do this), the select statement won't actually iterate through the collection in the way you might expect. The select statement will be translated into a query which can be understood by the IQueryProvider. Depending on what your datasource is, this could save bandwidth between you and the remote (SQL) and possibly allow a more optimised query.

  3. Had you not immediately called .ToList(), nothing would have happened until you enumerated the result. In some cases, this can save code ever being executed. There are times when it is better to avoid calling .ToList() to prevent the n+1 problem. There are also times it is better to call .ToList(), such as when you need to iterate the result multiple times.

This query could also be written:

var myItems = datasource.Select((i, item) => new MyObject
{
    Label = item.SourceName,
    LabelId = i,
    Data = item.TotalCount
}.ToList();

Which I find clearer personally, although that may be a matter of taste. It does have the advantage of removing the i variable from your scope, which is always nice and generally considered good practice.



回答2:

Short answer: nope, there is none as you call ToList on the first one you'd immediately force iteration which therefor will allocate the same memory.

Only difference that MIGHT be possible is the opportunity to create the instances within the first approach anonymously via select new { Label = ..., Data = ..., LabelID = i++ }.



回答3:

One of the things is exception line in the select the exception will tell you the line number of the select but for the foreach the exception will give you the real line number which in some cases this a must for me.