AsList() 比 ToList() 和 IDbConnection.Query() returns IEnumerable 更好吗?
Is AsList() better than ToList() with IDbConnection.Query() which returns IEnumerable?
我读了 Marc Gravell (@MarcGravell) 的回答:
最后一行说:
As a minor optimization to your code: prefer AsList() to ToList() to avoid creating a copy.
该语句是关于 QueryMultiple()
的,其中 return 是 GridReader
。
在我的理解中,System.Linq
提供了一个扩展方法IEnumerable.ToList()
。以下来自 Microsoft 关于 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()
将始终 return IEnumerable
或 null
。可以在调用代码中轻松完成空检查。那么 AsList
有什么不同呢?
如果我的理解是正确的,AsList
将始终在内部调用 ToList
,这将创建一个副本。
考虑到这一点,AsList()
比 ToList()
和 IDbConnection.Query()
哪个 return 比 IEnumerable
好?如果是;为什么?
在这种情况下,AsList()
在内部做了什么使其成为更好的选择?
AsList
是自定义的 Dapper 扩展方法。它所做的只是检查您传递给它的 IEnumerable<T>
是否真的是 List<T>
。如果是 - 它 return 返回,只是转换为 List<T>
。如果不是 - 它会调用常规 ToList
。关键是 - ToList()
总是创建一个副本,即使你传递给它的已经是一个列表。 AsList()
方法避免执行此复制,因此在不需要此类复制时很有用。
在此特定场景中,您有以下代码:
multipleresult.Read<MerchantProduct>()
其中 multipleresult
是 GridReader
。 Read
有 buffered
参数,默认为真。当它为真时 - Read
将真正 return List<T>
,因此通过调用 ToList
您将毫无理由地再次复制该列表。
对于IDbConnection.Query()
也是如此-也有buffered
参数,默认情况下为true,因此默认情况下也会return List<T>
.
如果您更喜欢使用 ToList()
- 您可以将 buffered: false
传递给 Query()
或 Read()
以避免创建额外的副本。
这个扩展是一个自定义的 dapper 扩展,它在调用 ToList
之前进行额外的检查。 Source:
public static List<T> AsList<T>(this IEnumerable<T> source)
=> (source == null || source is List<T>) ? (List<T>)source : source.ToList();
ToList
总是创建一个新的 List<T>
实例并用给定的项目填充它
AsList
检查序列是否已经是一个 List<T>
,然后它会直接转换它
当然,这种方法可以更有效,因为铸造一些东西比创建和填充新东西要少得多。所以完全不一样。
这是一种基于意见的观点,但我发现这很危险。有人可能会忽略 AsList
并阅读 ToList
或者只是不知道其中的区别。如果以后有人改代码就很危险了。
因此,例如采用 IEnumerable<T>
的方法使用 AsList
:
public static List<T> GetResult<T>(IEnumerable<T> seq)
{
if(some condition here)
{
seq = seq.Where(some predicate here);
}
return seq.AsList()
}
现在代码用一个列表调用这个方法:
IEnumerable<string> sequence = (gets a list from somewhere)
List<string> userList = GetResult(sequence);
后来有人认为数组更适合这里:
IEnumerable<string> sequence = (gets an array from somewhere)
List<string> userList = GetResult(sequence);
到现在为止这并没有真正伤害到。现在初始化并填充了一个新的列表,因为源不是列表并且无法转换。所以它的效率较低。但如果逻辑也依赖于列表是相同的引用,这将不再有效。
if(userList == seq)
{
// do something
}
一旦数组被使用,这总是 false
。于是悄无声息地破解了密码。
长话短说:我不喜欢 AsList
方法。您可以随时自己检查类型。
我读了 Marc Gravell (@MarcGravell) 的回答:
最后一行说:
As a minor optimization to your code: prefer AsList() to ToList() to avoid creating a copy.
该语句是关于 QueryMultiple()
的,其中 return 是 GridReader
。
在我的理解中,System.Linq
提供了一个扩展方法IEnumerable.ToList()
。以下来自 Microsoft 关于 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()
将始终 return IEnumerable
或 null
。可以在调用代码中轻松完成空检查。那么 AsList
有什么不同呢?
如果我的理解是正确的,AsList
将始终在内部调用 ToList
,这将创建一个副本。
考虑到这一点,AsList()
比 ToList()
和 IDbConnection.Query()
哪个 return 比 IEnumerable
好?如果是;为什么?
在这种情况下,AsList()
在内部做了什么使其成为更好的选择?
AsList
是自定义的 Dapper 扩展方法。它所做的只是检查您传递给它的 IEnumerable<T>
是否真的是 List<T>
。如果是 - 它 return 返回,只是转换为 List<T>
。如果不是 - 它会调用常规 ToList
。关键是 - ToList()
总是创建一个副本,即使你传递给它的已经是一个列表。 AsList()
方法避免执行此复制,因此在不需要此类复制时很有用。
在此特定场景中,您有以下代码:
multipleresult.Read<MerchantProduct>()
其中 multipleresult
是 GridReader
。 Read
有 buffered
参数,默认为真。当它为真时 - Read
将真正 return List<T>
,因此通过调用 ToList
您将毫无理由地再次复制该列表。
对于IDbConnection.Query()
也是如此-也有buffered
参数,默认情况下为true,因此默认情况下也会return List<T>
.
如果您更喜欢使用 ToList()
- 您可以将 buffered: false
传递给 Query()
或 Read()
以避免创建额外的副本。
这个扩展是一个自定义的 dapper 扩展,它在调用 ToList
之前进行额外的检查。 Source:
public static List<T> AsList<T>(this IEnumerable<T> source)
=> (source == null || source is List<T>) ? (List<T>)source : source.ToList();
ToList
总是创建一个新的List<T>
实例并用给定的项目填充它AsList
检查序列是否已经是一个List<T>
,然后它会直接转换它
当然,这种方法可以更有效,因为铸造一些东西比创建和填充新东西要少得多。所以完全不一样。
这是一种基于意见的观点,但我发现这很危险。有人可能会忽略 AsList
并阅读 ToList
或者只是不知道其中的区别。如果以后有人改代码就很危险了。
因此,例如采用 IEnumerable<T>
的方法使用 AsList
:
public static List<T> GetResult<T>(IEnumerable<T> seq)
{
if(some condition here)
{
seq = seq.Where(some predicate here);
}
return seq.AsList()
}
现在代码用一个列表调用这个方法:
IEnumerable<string> sequence = (gets a list from somewhere)
List<string> userList = GetResult(sequence);
后来有人认为数组更适合这里:
IEnumerable<string> sequence = (gets an array from somewhere)
List<string> userList = GetResult(sequence);
到现在为止这并没有真正伤害到。现在初始化并填充了一个新的列表,因为源不是列表并且无法转换。所以它的效率较低。但如果逻辑也依赖于列表是相同的引用,这将不再有效。
if(userList == seq)
{
// do something
}
一旦数组被使用,这总是 false
。于是悄无声息地破解了密码。
长话短说:我不喜欢 AsList
方法。您可以随时自己检查类型。