私はMarcGravell(@MarcGravell)からこの回答を読みました: https://stackoverflow.com/a/47790712/5779732
最後の行は言う:
コードのマイナーな最適化として:コピーの作成を避けるために、ToList()よりもAsList()を優先します。
そのステートメントは、GridReader
を返すQueryMultiple()
に関するものです。
私の理解では、_System.Linq
_は拡張メソッドIEnumerable.ToList()
を提供します。以下は MicrosoftToList()
についてです。
ToList(IEnumerable)メソッドは、クエリの即時評価を強制し、クエリ結果を含むリストを返します。クエリ結果のキャッシュされたコピーを取得するために、このメソッドをクエリに追加できます。
IDbConnection.Query()
は常にIEnumerable
またはnull
を返します。ヌルチェックは、コードを呼び出すときに簡単に実行できます。 AsList
はどのような違いをもたらしますか?
私の理解が正しければ、AsList
は常に内部的にToList
を呼び出し、コピーを作成します。
これを考慮すると、AsList()
はIEnumerable
を返すToList()
を使用するIDbConnection.Query()
よりも優れていますか?もし、そうなら;どうして?
AsList()
が内部的に行うことは何ですか?この場合、それはより良い選択になりますか?
AsList
はカスタムDapper拡張メソッドです。渡すのは_IEnumerable<T>
_が本当に_List<T>
_であるかどうかをチェックするだけです。もしそうなら-それはそれを返します、ただ_List<T>
_にキャストします。そうでない場合は、通常のToList
を呼び出します。重要なのは-ToList()
は、渡したものがすでにリストであっても、常にコピーを作成します。 AsList()
メソッドはこのコピーを回避するため、このようなコピーが不要な場合に役立ちます。
この特定のシナリオでは、次のコードがあります。
_multipleresult.Read<MerchantProduct>()
_
ここで、multipleresult
はGridReader
です。 Read
にはbuffered
引数があります。これはデフォルトでtrueです。真の場合-Read
は実際に_List<T>
_を返すので、ToList
を呼び出すことにより、理由もなくそのリストを再度コピーします。
同じことがIDbConnection.Query()
にも当てはまります。buffered
パラメータもあります。これはデフォルトでtrueであるため、デフォルトで_List<T>
_も返されます。
ToList()
を使用したい場合は、_buffered: false
_をQuery()
またはRead()
に渡して、追加のコピーが作成されないようにすることができます。
この拡張機能は、ToList
を呼び出す前に追加のチェックを行うカスタムdapper拡張機能です。 ソース :
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
を読んだり、違いがわからなかったりする可能性があります。後で誰かがコードを変更すると危険です。
したがって、たとえば、AsList
を使用するIEnumerable<T>
を受け取るメソッド:
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
メソッドが好きではありません。タイプはいつでも自分で確認できます。