代码之家  ›  专栏  ›  技术社区  ›  Amit Joshi

使用IDbConnection时,AsList()是否优于ToList()。返回IEnumerable的Query()?

  •  12
  • Amit Joshi  · 技术社区  · 7 年前

    我从MarcGravell(@MarcGravell)那里读到了这个答案: https://stackoverflow.com/a/47790712/5779732

    最后一行说:

    作为对代码的一个小优化:首选AsList()而不是ToList(),以避免创建副本。

    那份声明是关于 QueryMultiple() 它返回 GridReader .

    据我所知, System.Linq 提供扩展方法 IEnumerable.ToList() . 以下内容来自 Microsoft 关于 ToList() .

    ToList(IEnumerable)方法强制立即进行查询计算,并返回包含查询结果的列表。您可以将此方法附加到查询中,以获取查询结果的缓存副本。

    IDbConnection.Query() 将始终返回 IEnumerable null . 空检查可以在调用代码中轻松完成。有什么区别 AsList 那么是什么?

    如果我的理解是正确的, AsList公司 将始终在内部呼叫 ToList 这将创建一个副本。

    考虑到这一点 AsList() 优于 ToList() 具有 IDB连接。查询() 它返回 IEnumerable可数 ? 如果是;为什么?

    AsList() 在这种情况下,内部这是否使其成为更好的选择?

    2 回复  |  直到 7 年前
        1
  •  19
  •   Evk    7 年前

    AsList 是一种自定义的Dapper扩展方法。它所做的只是检查 IEnumerable<T> 你传给它真的 List<T> . 如果是-它将其返回,只需将其转换为 列表(<);T> . 如果不是,则称为常规 ToList . 重点是- ToList() 始终创建副本,即使传递给它的内容已经是一个列表。 AsList()

    在此特定场景中,您有以下代码:

    multipleresult.Read<MerchantProduct>()
    

    哪里 multipleresult GridReader . Read buffered 默认情况下为true的参数。当它是真的- 阅读 真的会回来 列表(<);T> ,所以通过呼叫 托利斯特 你会无缘无故地再次复制这份清单。

    这同样适用于 IDbConnection.Query() -is也有 缓冲的 参数,默认情况下为true,因此默认情况下也会返回 列表(<);T> .

    如果您喜欢使用 ToList() -你可以通过 buffered: false Query() Read() 以避免创建额外副本。

        2
  •  4
  •   Tim Schmelter    7 年前

    此分机是一个自定义dapper分机,在调用之前进行额外检查 ToList . Source :

    public static List<T> AsList<T>(this IEnumerable<T> source) 
        => (source == null || source is List<T>) ? (List<T>)source : source.ToList();
    
    • 托利斯特 始终创建新的 List<T> 实例并用给定项填充它
    • AsList 检查序列是否已为 列表(<);T> ,那么它就会投下它

    当然,这种方法可能更有效,因为铸造某种东西比创建和填充新东西要省力得多。所以完全不同。

    这是基于观点的,但是 我觉得这很危险 . 有人可能会忽视 AsList公司 并阅读 托利斯特 或者只是不知道区别。如果以后有人更改代码,那是很危险的。

    例如,一种方法 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公司 方法你可以自己检查类型。