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

我与影子孤独终老i 提交于 2019-12-03 12:49:39

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.

This extension is a custom dapper extension which does an additional check before calling ToList. Source:

public static List<T> AsList<T>(this IEnumerable<T> source) 
    => (source == null || source is List<T>) ? (List<T>)source : source.ToList();
  • ToList always creates a new List<T> instance and fills it with the given items
  • AsList checks if the sequence is already a List<T>, then it will just cast it

Of course this approach can be more efficient because casting something is much less work than creating and filling something new. So it's completely different.

This is kind of opinion based, but i find this dangerous. Someone might overlook the AsList and reads ToList or just don't know the difference. It's dangerous if someone changes the code later.

So for example a method that takes IEnumerable<T> which uses AsList:

public static List<T> GetResult<T>(IEnumerable<T> seq)
{
    if(some condition here)
    {
        seq = seq.Where(some predicate here);
    }
    return seq.AsList()
}

Now code called this method with a list:

IEnumerable<string> sequence = (gets a list from somewhere)
List<string> userList = GetResult(sequence);

Later someone decides that an array is more appropriate here:

IEnumerable<string> sequence = (gets an array from somewhere)
List<string> userList = GetResult(sequence);

This doesn't really hurt until now. Now a new List is initialized and filled because the source is not a list and can't be casted. So it's just less efficient. But if the logic also relied on the list being the same reference, this won't work anymore.

if(userList == seq)
{
    // do something
}

This is always false once the array is used . So the code was broken silently.

To cut a long story short: i don't like the AsList method. You can always check the type yourself.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!