| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

差分

ナビゲーションに移動 検索に移動
編集の要約なし
==プログラミングC#(2) LINQ==| [[言語 まとめ 言語まとめ C#Sharp]]| [[C#Sharp]] | [[C# Sharp サンプルコード]] | [[Effective C# Sharp 4.0]] | [[Universal Windows Platform]] | [[Visual Studio]] | {{amazon|4873116503}}
==プログラミング[[C#]](2) LINQ==*[[プログラミングC Sharp 第7版|プログラミングC# 第7版]]*[[プログラミングC Sharp 第7版(1)|プログラミングC# 第7版(1)]]
{{amazon|4873116503}}
{{amazon|4798153826}}
*https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
==基本==
*言語統合クエリ[[言語]]統合クエリ*連携して動作するいくつかの言語要素から構成連携して動作するいくつかの[[言語]]要素から構成
**クエリ式
**LINQ演算子
**LINQプロバイダ
*[[.NET ]] Framework
====オブジェクト用====
*LINQ to Objects
====データベース用====
*[[SQL Server用 Server]]用 LINQ to SQL
*汎用 LINQ to Entities
====WCFデータサービスクライアント====
<&lt;blockquote>&gt;あらゆるオブジェクトコレクションに対してLINQを使用してみると非常に便利<&lt;/blockquote>&gt;
===クエリ式(クエリ構文)===
*多くの種類のクエリを非常に自然な文法で記述できる
=====例1=====
int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
IEnumerable<[[IE]]numerable&lt;int> &gt; odd =
from num in nums
where num % 2 == 1
=====例2=====
var result = from book in books
where book.Title.IndexOf("計算") > &gt; 0
orderby book.Title descending
select book.Title
=====データソース=====
*クエリのソースを確定
*IEnumerable[[IE]]numerable/IEnumerable<[[IE]]numerable&lt;T> &gt; インターフェース、またはその派生インターフェースを実装していることだけが条件
*foreachで処理できるオブジェクトであれば利用できる
**オブジェクト配列、データセット、XElementオブジェクト配列など
*出力を決定
*出力結果の型は、select句もしくはgroup句によって決まる
*すべてのクエリ式が IEnumerable<[[IE]]numerable&lt;T> &gt; となるわけではない
**プロバイダによって決まる
**var を結果利用することが一般的
=====例1=====
int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
IEnumerable<[[IE]]numerable&lt;int> &gt; odd = nums .Where(num => &gt; num % 2 == 1) .OrderByDescending( book=> &gt; book.Title) .Select(num => &gt; num);
foreach (var n in odd)
=====例2=====
var result = books
.Where( book => &gt; book.Title.IndexOf("計算") > &gt; 0 ) .Select( book => &gt; book.Title)
;
*クエリ式で、サブ式の結果を格納して後の句で使用すると便利な場合があります。 let キーワードを使用すると、これを行うことができます
int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
IEnumerable<[[IE]]numerable&lt;int> &gt; odd =
from num in nums
let r = num % 2
===遅延評価===
*必要なときのみ動作するオブジェクトを返す
<&lt;blockquote>&gt;クエリの結果を取得しようとしたときのみ実際に処理が行われる<&lt;/blockquote>&gt;
*無限シーケンスを処理できる
*クエリが何度も評価されないように注意する必要がある
===LINQ、ジェネリックとIQueryable<&lt;T>&gt;===
*ほとんどのLINQプロバイダでは、ジェネリック型が使われている
*LINQ to Objects では IEnumerable<[[IE]]numerable&lt;T> &gt; が使われている*データベース用プロバイダでは、IQueryable<&lt;T> &gt; を使うものがある
==標準LINQ演算子==
*演算子とはLINQプロバイダが提供するクエリ機能のこと
**単純な項目に対して複雑なクエリを実行できる
**ほとんどの演算子が項目の集合を表す型を引数に取るだけでなく結果として返す
**LINKQ演算子は数学的な関数LINKQ演算子は[[数学]]的な関数
*入力に影響を与えない
*結果は新しく生成される
**インデックスを伴うWhere演算子
int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
IEnumerable<[[IE]]numerable&lt;int> &gt; odd = nums.Where((r, idx) => &gt; { Console.WriteLine($"IDX:{idx}"); return r % 2 == 1; });
*条件に合ったオブジェクトがない場合空のシーケンスを生成
====OfType<&lt;T>&gt;====
*特定の型の項目だけを取り出したいときに便利
var strings = src.OfType<&lt;string>&gt;();
*条件に合ったオブジェクトがない場合空のシーケンスを生成
====最終的に出力される項目を指定するラムダを渡すためにクエリの最後にselect句を書く====
*必要なプロパティだけを含む匿名型のインスタンスを返す
var pq = from product in dbCtx.Products
where (product.ListPrice > &gt; 3000)
select new { product.Name, product.ListPrice, product.Size };
====射影とマップ====
*Select演算子は射影と呼ばれることがあるが、mapと同じもの
*Selectは概念的には Selectは[[概念]]的には Map Reduce の一部と同じ命令(LINQでは reduce に対して Aggregate と命名)
====SelectMany====
*複数のfrom句を持つクエリ式の中で使用される
int[] nums = { 1, 2, 3, 4, 5 };
char[] alphas = { 'a', 'b', 'c', 'd', 'e' };
IEnumerable<[[IE]]numerable&lt;string> &gt; strs = from num in nums
from alpha in alphas
select alpha + num.ToString()
int[] nums = { 1, 2, 3, 4, 5 };
char[] alphas = { 'a', 'b', 'c', 'd', 'e' };
IEnumerable<[[IE]]numerable&lt;string> &gt; strs = nums.SelectMany(num => &gt; alphas, (num,alpha) => &gt; alpha + num.ToString());
====取得列を明示的に指定====
*2つのオーバーロード
**項目を引数にとる
**--IList<&lt;T>&gt;を実装するコレクションの場合、IList<&lt;T> &gt; のContains が利用される**項目+IEqualityComparer<項目+[[IE]]qualityComparer&lt;T> &gt; 型の引数をとる
====Any====
*コレクションが特定の条件を満たす値を1つ以上含んでいるか
*predicateをとる
**intを返す
condition.ResultCount [[R]]esultCount = db.SearchConditionResultsSearchCondition[[R]]esults.Count(src => &gt; src.SearchConditionId == condition.Id);
====LongCount====
*非常に大きな値の個数
&& table.tabname == id
select table).SingleOrDefault();
====[[その他]]====
{|class="wikitable"
!機能
|Last,LastOrDefault
|-
|指定した数の要素をスキップしてその他すべてを返す指定した数の要素をスキップして[[その他]]すべてを返す
|Skip
|-
|-
|}
空でない限りソースのコレクション全体が返される、空の場合 T型のゼロに相当する規定値参照型:null、数値型:0)を持つ一つの項目を含むシーケンスを返す,DefaultIfEmpty<&lt;T>&gt;
====集約====
{|class="wikitable"
====Max,Min====
*数値型のコレクションに備わる
double av = (new List<&lt;int>&gt;{12,123,5,6546,8,9,1}).Average();
*あらゆる型の項目に対して動作するオーバーロード版
**ラムダを引数に取る
var ttlAge = persons.Sum(person => &gt; person.Age); var avAge = persons.Average(person => &gt; person.Age); var mxAge = persons.Max(person => &gt; person.Age); var mnAge = persons.Min(person => &gt; person.Age);
====Aggregate====
**すべてを調べて1つの値を得る演算子を一般化
**--合計、最大、平均を書き換える
var s2 = persons.Aggregate(0.0, (ttl, person) => &gt; ttl + person.Age); var m2 = persons.Aggregate(0.0, (max, person) => &gt; max > &gt; person.Age ? max : person.Age); var a2 = persons.Aggregate(new { ttl=0, cnt=0 }, (p1, person) => &gt; new { ttl = p1.ttl + person.Age,cnt = p1.cnt + 1 }, p2 => &gt; p2.ttl / p2.cnt);
**累積器
**reduce と呼ばれる機能のLINQにおける名称
*2つのソースをまとめる
*一般的な集合演算
*数学の集合とは異なる[[数学]]の集合とは異なる
====Distinct====
**--重複を取り除く
**どちらか、もしくは両方に含まれる
====シーケンス全体を扱ったり、順序を維持するための演算子====
====Reverse[[R]]everse====
*要素の順序を反転
====Concat====
string[] nums = { "1", "2", "3", "4", "5" };
string[] alphas = {"a", "b", "c", "d", "e" };
var zipped = nums.Zip(alphas, (num, alpha) => &gt; num + ":" + alpha);
foreach( string s in zipped)
{
===グループ化===
====group句====
*IGrouping<&lt;TKey,TItem> &gt; を実装する項目のコレクションを生成する var persons = new List<&lt;Person> &gt; {
new Person() { Team="A",Name="hoge" },
new Person() { Team="B",Name="foo" },
**into キーワードによりクエリの残りで反復処理するための範囲変数が作られる
**--orderbyやwhereなどほかの句でも利用できる
**規定の結果IGrouping<&lt;TKey,TItem>&gt;も変更できる
var teams = from person in persons
group person by person.Team into team
select $"Team:{team.Key}:{team.Count()}";
====グループ射影を使ったグループ化クエリの展開====
var teams = persons.GroupBy(person => &gt; person.Team) .Select(team => &gt; $"Team{team.Key}:{team.Count()}");
**同じ意味を直接的に表すオーバーロド
**--2つのラムダをとる
**----2つめはグループオブジェクトを生成するため
**------最初の引数にKeyが渡る
var teams = persons.GroupBy(person => &gt; person.Team, (teamName,team) => &gt; $"Team{teamName}:{team.Count()}");
====キー、項目とグループの射影を使ったGroupBy演算子====
**3つのラムダをとる
**--各オブジェクトを生成
var teams = persons.GroupBy(
person => &gt; person.Team, person => &gt; person.Name, (teamName,names) => &gt; $"Team{teamName}:{names.Count()}");
====複合グループキー====
**複数のキーでグループ化したい場合、単純にキーに両方の値を入れる
var persons = new List<&lt;Person> &gt; {
new Person() { Team="A",Name="hoge1",Lank="1" },
new Person() { Team="A",Name="hoge2",Lank="1" },
===Join===
*異なるソースから関連性のあるデータをクエリから使用できるようにする
var teams = new List<&lt;Team> &gt; {
new Team() {Code="A",Name="TeamA" },
new Team() {Code="B",Name="TeamB" },
new Team() {Code="C",Name="TeamC" }
};
var persons = new List<&lt;Person> &gt; {
new Person() { Team="A",Name="hoge1"},
new Person() { Team="B",Name="foo"},
}
====複合キーで結合する====
var teams = new List<&lt;Team> &gt; {
new Team() {Code="A",SubCode="1",Name="TeamASub1" },
new Team() {Code="B",SubCode="1",Name="TeamBSub1" },
new Team() {Code="C",SubCode="1",Name="TeamCSub1" }
};
var persons = new List<&lt;Person> &gt; {
new Person() { Team="A",TeamSub="1",Name="hoge1"},
new Person() { Team="B",TeamSub="1",Name="foo"},
===変換===
====シーケンスの型変換====
var sourceSeq = sequence.Cast<&lt;Cource>&gt;();====Cast<&lt;T>&gt;====
*変換不能な場合、例外をスローする
====OfType<&lt;T>&gt;====*Cast<&lt;T> &gt; とほとんど同じだが、間違った型が存在した場合、例外をスローせずフィルタする====AsEnumerable<&lt;T>&gt;====
*何ら変更なくソースを返す
*他のLINQプロバイダーによって処理される可能性があるものを扱う場合でも、確実にLINQ to Objectsによって処理されるようにする
*ここから先はクライアント側で処理をすると明示
====AsQueryable<&lt;T>&gt;====*AsEnumerable<&lt;T>&gt;の反対に、LINQ to Objectsの代わりに確実に自分で作成したクエリを使用したいようなシナリオ
====AsParallel====
*Parallel LINQ(PLINQ)によって実行されるクエリを構築するためのParallelQuery<&lt;T> &gt; が返される
====ToArray,ToList====
*入力クエリを実行した結果のすべてを格納した配列、リストが返される
====ToDictionary,ToLookup====
*連続ルックアップをサポートした結果を生成
*--IDictionay<&lt;TKey,TValue>&gt;,ILookup<&lt;TKey,TValue>&gt;が返される var persons = new List<&lt;Person> &gt; {
new Person() { Team="A",Name="hoge1"},
new Person() { Team="A",Name="hoge2"},
new Person() { Team="C",Name="fuga"}
};
var ta = persons.ToLookup(person => &gt; person.Team);
foreach (var p in ta["A"])
{
}
==シーケンスの生成==
====Enumerable.Range[[R]]ange====*2つのintをとり、2つ目の引数まで1づつ大きくなるIEnumerable<2つのintをとり、2つ目の引数まで1づつ大きくなる[[IE]]numerable&lt;int>&gt;を返す====Enumerable.Repeat<[[R]]epeat&lt;T>&gt;====
*型Tと回数を引数にとり、指定した回数生成する
====Enumerable.Empty<&lt;T>&gt;====*要素のないIEnumerable<要素のない[[IE]]numerable&lt;T>&gt;が返される
==他のLINQの実装==
===Entity Framework===
====LINQ to Entities====
*[[.NET ]] Frameworkの一部
*データベースとオブジェクト層を対応づけ
*複数のデータベースベンダ製品がサポート
*IQueryable<&lt;T> &gt; を使用**IEnemerable<[[IE]]nemerable&lt;T> &gt; から派生しているのでLINQ to Objectsの演算子を利用できる
*匿名メソッドやデリゲートは使用できない
====LINQ to [[SQL]]====*[[SQL ]] サーバー専用の設計*[[.NET ]] API として設計*テーブルオブジェクトが、IQueryable<&lt;T> &gt; を実装
====WCF データサービスクライアント====
*Open Data Protocol(OData)を使用してHTTP上でデータを表現したり消費するを使用して[[HTTP]]上でデータを表現したり消費する*XML もしくは [[JSON]]*IQueryable<&lt;T>&gt;を使用
*一部のLINQ演算子のみサポート
===Parallel LINQ===
====クエリの結果を取得する際、可能であれば使用可能なCPU資源を効率的に使用するため、スレッドプールを使ったマルチスレッドの評価が行われる====
====LINQ to [[XML]]====
*LINQプロバイダではない
*XMLを作成すしたり、パースするためのAPI[[XML]]を作成すしたり、パースするためのAPI*XML文書に対して簡単にLINQクエリを実行できるように設計されている[[XML]]文書に対して簡単にLINQクエリを実行できるように設計されている*XML文書を [[.NETオブジェクトモデルで表現することで実現NET]]オブジェクトモデルで表現することで実現*完全に[[.NETに向けて設計されているため、CNET]]に向けて設計されているため、C#技術と非常によく統合されている
*LINQ to Objectsと同様な方法でクエリの定義、実行が可能
===[[Reactive Extensions]]===
*LINQ演算子が様々な型とともに動作する仕組みをうまく表している

案内メニュー