Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is AsList() better than ToList() with IDbConnection.Query() which returns IEnumerable?

I read this answer from Marc Gravell (@MarcGravell): https://stackoverflow.com/a/47790712/5779732

The last line says:

As a minor optimization to your code: prefer AsList() to ToList() to avoid creating a copy.

That statement is about QueryMultiple() which returns GridReader.

In my understanding, System.Linq provides an extension method IEnumerable.ToList(). Following is from Microsoft about ToList().

The ToList(IEnumerable) method forces immediate query evaluation and returns a List that contains the query results. You can append this method to your query in order to obtain a cached copy of the query results.

IDbConnection.Query() will ALWAYS return IEnumerable or null. Null-check could be easily done in calling code. What difference does AsList makes then?

If my understanding is correct, AsList will always internally call ToList which will create a copy.

Considering this, is AsList() better than ToList() with IDbConnection.Query() which returns IEnumerable? If yes; why?

What is that AsList() does internally that makes it a better choice in this case?

like image 436
Amit Joshi Avatar asked Dec 13 '17 13:12

Amit Joshi


1 Answers

AsList is a custom Dapper extension method. All it does is checks if IEnumerable<T> you pass to it is really List<T>. If it is - it returns it back, just casts to List<T>. If it's not - it calls regular ToList. The point is - ToList() always creates a copy, even if what you pass to it is already a list. AsList() method avoids doing this copy, and so is useful if such copy is unnecessary.

In this specific scenario, you have the following code:

multipleresult.Read<MerchantProduct>()

where multipleresult is GridReader. Read has buffered argument which is true by default. When its true - Read will really return List<T>, so by calling ToList you will copy that list again without much reason.

The same is true for IDbConnection.Query() - is also has buffered parameter, which is true by default, so it will also by default return List<T>.

If you prefer to use ToList() - you can pass buffered: false to Query() or Read() to avoid creating that additional copy.

like image 97
Evk Avatar answered Sep 21 '22 05:09

Evk