【VB.NET】LINQ友の会【C#, C♯, C#】

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん
垢版 |
2008/02/09(土) 23:51:34
VisualStudio2008より追加された便利で強力な機能

  統合言語クエリ (LINQ : Language Integrated Query)

ちょっと使ってみると、意外と難しいし、テクニック的にも奥が深いものです。
関数型言語にしかないような機能ラムダ式(Lambda式)などはオブジェクト指向とは一味違う機能です。
DataBaseの操作にも、Xmlの操作にも、さらにもっと単純な配列なコンテナにさえ機能する
言語共通・高汎用な統合言語クエリを皆で一緒にマターリ勉強しましょう。
質問、便利なマイテクニックの発表、いろいろやっちゃってください。
2009/11/15(日) 03:02:15
() => { yield return item; }
2009/11/15(日) 10:18:15
ラムダ内をイテレーターブロックにはできないよ。
やるなら、拡張メソッド追加して、

public static IEnumerable<T> Concat(this T x, IEnumerable<T> list)
{
yield return x; foreach(var i in list) yield return i;
}
public static IEnumerable<T> Concat(this IEnumerable<T> list, T x)
{
foreach(var i in list) yield return i; yield return x;
}
2009/11/15(日) 11:46:45
>>461
Enumerable.Repeat(item, 1) で回避。
465デフォルトの名無しさん
垢版 |
2009/11/15(日) 12:01:40
拡張メソッドにT使えたっけ?
466デフォルトの名無しさん
垢版 |
2009/11/15(日) 12:17:35
Concat<T>が正解ね
2009/11/15(日) 16:28:58
>>464
それたぶん配列作った方が効率的
Rangeで作られるイテレータよりも配列のイテレータの方がずっと速いはず
468467
垢版 |
2009/11/15(日) 16:30:40
間違えたRepeatか
2009/12/11(金) 00:11:22
Linq to Object で List 内のデータを取り出した時に、そのデータを変更することはできるのでしょうか?
Linq to Object では、抽出するだけなのでしょうか?
2009/12/11(金) 00:17:14
>>469
List 自体の更新?
LINQ 以前に、GetEnumerator で列挙してる最中にリストのアップデートかけちゃダメ。

list[i] = xxx; 的なことがしたいって場合も、GetEnumerator じゃ無理。

list[i].Property = xxx; 的なことなら、
foreach (var x in list.Select(xxx)) x.Property = xxx; で可能。
471469
垢版 |
2009/12/11(金) 23:15:10
>>470
ありがとうございます。
LINQ は便利だなぁと(ソートもしてくれるし), PLINQ にもなるし;

抽出した内容を判別して、データを変更できるんだろうなぁと思っていました。

2009/12/12(土) 14:18:30
ちなみに、標準では Foreach メソッドみたいなのないけど、
それを認めると LINQ 中で副作用起こすのを推奨しちゃうことになるから避けたらしい。

list.Select(x => xxx).Foreach(x => x.Property = xxx);
みたいなのは邪道。
LINQ 中では副作用は起こさないこと推奨。
2009/12/12(土) 14:47:28
なれていない人って偶に
 int count = 0; var distList = from i in srcList select new { Val=i, Index=++count };
みたいな事をやっちゃうよねw

そういうノウハウってどこかにまとまっていないのだろうか?
MSDNにLINQの使い方ガイドラインってないよね?
2009/12/12(土) 15:48:41
外部スコープの変数を書き換えるといろいろ副作用が怖いね。
よほど理解して使わないと。
475デフォルトの名無しさん
垢版 |
2009/12/12(土) 18:32:10
副作用?そんな表現はじめて聞いた。
msが言ってるの?
2009/12/12(土) 18:45:02
一般的な言葉じゃないか?
「ifの中に副作用のある式を書くな」なんて昔から言われているし
2009/12/12(土) 18:50:51
Linqというよりそこで使われてる静的クロージャの問題。
.NET2.0でクロージャが実装されたとき有名になったプログラム。
i, j がどんな値になるか想像つく?
using System;
using System.Collections.Generic;
delegate void F();
class Test {
  static void Main() {
    List<F> actionList = new List<F>(); 
    for(int i = 0; i < 10; ++i) {
      int j = i;
     actionList.Add(delegate(){Console.WriteLine("i={0}, j={1}",i, j);}); 
    }
    foreach (F f in actionList) f();
  }
}
2009/12/12(土) 20:20:23
LINQの副作用関連でのエンバグは、>>477以外に遅延評価に原因しているものもあると思う
標準的な使い方である「LINQ中でselect new」すら副作用のある式なわけで
(戻り値を使う場所も含め)ちゃんとその挙動まで把握しないと不味い。

var hoges = from p in hoge select new Hoge(p);
foreach(var hoge in hoges) { hoge.ValueChanged += Hoge_OnValueChanged(); }
foreach(var hoge in hoges) { hoge.Value = 3; } // Hoge_OnValueChanged………?

そこまで考慮している保証のないクラスや関数に
値を渡す/返す場合は常にToArray/ToListするのが正解か
479デフォルトの名無しさん
垢版 |
2009/12/13(日) 03:24:35
そりゃそうだろw
何言ってんのw
2009/12/13(日) 03:41:07
>477
のは気をつけないと忘れてて、あれうごかねぇとかたまにやるw最近は体が覚えてきたが。
>478
うちのバカエンジニアとかでもおなじようなことしてそうでこえぇ。
2009/12/13(日) 19:31:28
>>479
自分一人ならこういうノウハウもすぐに納得して「そりゃそうだ」で済ませれるが、
仕事でチームでやっていると全員がLINQを理解しているわけじゃないから、そうもいかないのよね。

気がつくと新人がコメントに「//なぜかこのToListを外すとぬるぽ」とか書いてたりするw
482デフォルトの名無しさん
垢版 |
2009/12/14(月) 13:13:04
そんなこと言ってたら新しいことなんもできんやろ
未熟な人間にあわせてどうすんねんw
2009/12/14(月) 17:16:24
まともな業務アプリの開発だと、LINQでDBアクセスなんてしないから(つーか、したらバカ)
そんなに大して問題にはならない。
クライアントサイドでリスト形式の一時データを参照をする場合になら使える程度だと思う。
2009/12/14(月) 17:30:49
そうは言ってもLinqなしでEntityFrameworkを使うのはつらいぞ(笑
自分の理解できないものを嫌う気持ちもわからんではないがね。
そういう人はLinq以前にORMも使えないのだろう。
2009/12/14(月) 22:08:07
>>482
新しい技術を導入したらアホがアホなことをしないように、
実装規約やガイドラインを用意しなきゃならんのよ。辛いことに。
2009/12/15(火) 06:45:06
LINQ漬けになるとトランザクションを意識しない楽観的な思考になりやすい。
そしてDB更新系で落とし穴に。。。
2009/12/15(火) 22:32:42
TransactionScope 使えるんだし大丈夫じゃね?
2010/01/15(金) 22:13:23
・意味不明な所で例外が起こってトラブったら、LINQの遅延評価が原因だったでござる。
・想定外の値が返ってくると思ったら、LINQの遅延評価+キャプチャが原因だったでござる。
・新人が遅延評価+ソースの値の変更を前提としたコードを作っていたでござる
コードの各所に見えない依存関係ができてもうやだ…
自分のコードは副作用のないようにしているが、他人のコードはどこまで追っかけても分からん…
2010/01/16(土) 01:16:01
.Selectで検索して全部ToList()すれば?w
2010/01/16(土) 01:49:49
遅延評価前提ってのは別にいいんじゃないの?
後段に更に条件を繋げられるようになるのだから、指針としては悪くない。
キャプチャのほうは本当に注意深くやらなきゃいけないのに、無頓着な人いるよね……
2010/01/16(土) 10:37:33
チーム規約で、ToList 必須にしちまえば?
492デフォルトの名無しさん
垢版 |
2010/01/16(土) 10:40:55
キャプチャってどういう意味?
わからないから聞いちゃう><
2010/01/16(土) 14:50:19
頼み方が悪いから教えない
2010/01/16(土) 14:50:23
クロージャで外のローカル変数を取り込むやつかな
それを利用して長く状態持たせたりすると凶悪
495デフォルトの名無しさん
垢版 |
2010/01/16(土) 14:55:39
それでもGCがなんとかしてくれるんでしょ?
もしかしてunsafeがらみの話?
2010/01/16(土) 15:05:45
そういう話じゃなくてさ
int i = 0;
otherClass.Items = source..Where(x=>x.Value == i++);
こんなことされるともうどうなるか分からないだろ
OtherClassのItemsの評価回数に依存することになる
2010/01/16(土) 21:53:13
>>496
いいたいことはわかるが動くコードかこうな。
説得力ないから。
2010/02/04(木) 18:12:53
すみません、質問です。
LINQには、バージョンはあるのでしょうか?
VS等のバージョンはどんどんとあがっていっていますが、
コードが同じもので動かなくなるかどうかを知りたいです。
例えば、CLRに完全依存の構造なので、CLRバージョンが変わる時に
注意が必要、など
2010/02/04(木) 20:54:49
基本的に上位互換だから気にしなくていい
2010/02/05(金) 13:27:50
すみません、質問です。
LINQで更新や削除は行えるのでしょうか?
たとえ行えたとしても、細かい制御が出来ないからADO.NETで
ExecuteNonQuery使った方が楽っていう結論になってたりするのかな?
2010/02/05(金) 13:29:30
Linq to SQL
Linq to Entity
両方ともORMだから可能。
2010/02/05(金) 13:52:18
いったんエンティティに読み込むから大域処理には向いてないな。
2010/02/05(金) 19:05:38
一括更新用の拡張メソッドを作っている人達もいるな。
2010/02/05(金) 19:26:15
テーブルは第3正規化がされているのが普通だし、多数の表の集合演算が入るから
結局はエンティティと対になるストアドプロシージャを組んでしまう。LINQ気持ち悪い。
2010/02/05(金) 21:36:19
LINQは排他制御がきちい
2010/02/07(日) 17:03:06
L2Sは更新がちょっとという人は、DataContext.GetCommand(query).CommandTextで取得した
WHERE句を元にUPDATE句やDELETE句を組み立てて、DataContext.ExecuteCommand()を実行する
ような拡張メソッドを用意するのが良いと思うよ。

そうすれば、更新処理はADO.NETを使ってベタでとかやらずに、トランザクションや排他に
ついてはExecuteNonQueryと同じ考え方で設計出来るから。

っで、それ以上の事をやりたくなったらストアドで。
2010/02/08(月) 01:17:13
>>506
結局はSQLを書くってこと?LINQの意味なくない?
2010/02/08(月) 06:55:49
この辺を参考に。
ttp://weblogs.asp.net/jeffreyzhao/archive/2008/03/06/linq-to-sql-extension-batch-deletion-by-lambda-expression.aspx
ttp://www.aneyfamily.com/terryandann/post/2008/04/Batch-Updates-and-Deletes-with-LINQ-to-SQL.aspx
509デフォルトの名無しさん
垢版 |
2010/02/13(土) 17:28:02
Distinct重複は取り除けるけど、重複しているものだけを
取り出すには、どうすればいい
2010/02/13(土) 17:48:11
groupbyしてwhere count>2って感じ。
511デフォルトの名無しさん
垢版 |
2010/02/13(土) 18:48:06
>>510 サンクス

int[] numbers = { 5, 4, 1, 3, 9, 5, 8, 4, 6, 7, 2, 5, 0 };
var Nums = numbers.GroupBy(num => num).Where(num => num.Count() >= 2);
foreach (var x in Nums)
  Console.WriteLine("{0}:{1}",x.Key,x.Count());
2010/02/13(土) 19:27:29
そこらへんはLINQというよりSQLのセンスだよな。
2010/02/13(土) 20:55:57
LINQ 初めて使ってみたけどなんか面白いね
ていうか拡張メソッドが面白いのか
2010/02/13(土) 20:59:49
何も考えずに乱用すると破綻するけどねw
2010/02/13(土) 21:50:24
基本DBはストアドを呼び出し。もし必要であればEntityの複合型データにLINQ。
という使い分け。テーブルには絶対にLINQでアクセスしない。
MVVMデザインアプローチで組んでいるが、まずLINQの出番はない。
2010/02/13(土) 21:57:31
Linq to Object は使うわ
2010/02/13(土) 22:22:07
>>514
やべえ調子に乗って使いまくるところだったww
2010/02/13(土) 23:04:13
自分は、L2Sに関しては式ツリーからSQLを生成するライブラリだという捉え方。
他のLINQ to ホゲホゲについてはまた別の捉え方だけど。
2010/02/13(土) 23:06:47
メソッド形式のto Objectsは普通に便利
メソッド形式で使ってる限りはループで書くのに比べて見づらくなることもまず無いし
2010/02/13(土) 23:16:26
to IQueryableなものとto IEnumerableなものでは考え方は違うわな。
2010/02/14(日) 00:03:10
LINQはCollectionデータだけを対象にして使う分にはいいね。
2010/02/14(日) 00:14:49
まぁ大抵の感想はそこにいきつく。
無理にLINQtoSQLを使うことはない。
2010/02/14(日) 00:24:09
Expressionで処理を構築するっていう考え方は割と好きだけどね−。
2010/02/14(日) 00:25:34
IEnumerable に ForEach がないのは何でなんだろ
2010/02/14(日) 00:36:00
>>524
副作用起こす系統はLINQの標準には入れたくなかったんじゃないかと。
2010/02/14(日) 00:36:11
>>524
>>472

まぁそれでも作ろうと思えば
public static void Foreach(this IEnumerable<T> source, Action<T> callback) { foreach(var i in source) callback(i); }
簡単に自作できちゃうが。
2010/02/14(日) 00:45:40
>>525-526
なるほどー
>>526
それ作ったw
2010/02/14(日) 13:40:26
C#って3.0以降は標準化されてないけどするとしたらExpression<T>とかdynamicとかどうするんだろう
激しくランタイムに依存するわけだけど全部言語仕様にハードコードするのかな
2010/02/15(月) 20:27:09
お邪魔します。
実はわりと短期間でACCESS+MySQLで作ったアプリを少し拡張して
VB.NET2008 Expressに移植しないといけないのです。

ACCESS VBAでO/Rマッピングもどきを自作で実装していたのですが、
コーディング効率アップのためにLINQの採用を検討しています。

・単純に、"ODBC経由でMySQLにつないでテーブルから任意のカラムを取ってくる"
 というサンプルソースか手順リストがどこかにありませんでしょうか?
 ネットで探しまくっているのですが、LINQ布教用のXMLやら配列やらへの
 クエリのサンプルは見つかっても、実用的なMySQL/ODBCへの接続宣言を
 どうするのかが見つからないのです。

・LINQの習得にADO.NETの知識は必須でしょうか?
 DAO、ADOときて、これ以上、知識の習得に無駄な寄り道は出来れば
 避けたいのですが。

みなさん、よろしくお願いします。
2010/02/15(月) 21:06:51
お前にとっては多分無駄な寄り道だと思うからやめとけば
2010/02/15(月) 21:09:51
普通に考えてそのまんま移植した方が早い
2010/02/15(月) 21:38:19
探しまくっても見つからないようなもんが
なんで効率アップに繋がると思うのがよくわからんわ
2010/02/15(月) 22:07:19
LINQ プロバイダ MySQL でぐぐってわからなかったら無理だからやめておけ
2010/03/14(日) 22:49:42
xmlはUTF-8だと思っていたけど、XmlDocument.Load(TextReader)
でTextReaderにS-jisエンコードを指定しているコードをみて困惑。
これってどういう意図なんでしょう?
2010/03/15(月) 02:22:37
ていうかXMLはUTF-8じゃないというか、何だってありだし。
UTF-8固定ならDeclarationにencodingはいらん。
2010/03/16(火) 00:47:57
まあそういうなよ
537デフォルトの名無しさん
垢版 |
2010/03/18(木) 01:22:17
UTF-8はデフォルトなだけ
2010/03/30(火) 00:55:11
なんか来てた
Chapter16 LINQとメソッド構文
ttp://www.atmarkit.co.jp/fdotnet/extremecs/extremecs_16/extremecs_16_01.html

でもこんな概略の説明なんて既に色々あるんだから、もっと深い奴、
例えばLINQの落とし穴とかそういうところを説明したドキュメントがホスィ
2010/03/30(火) 08:10:45
コアな使い方はブログを見て回ればいいんじゃね?
2010/03/30(火) 09:38:37
それがマンドクサイのでいろいろとコアなのがまとまってて欲しいのが正直なところ。
いや、そんなことじゃいけないとは思うんだけどね(;´Д`)
541デフォルトの名無しさん
垢版 |
2010/06/05(土) 19:53:02
今更ながらLINQ便利すぎ!
Listに格納したオブジェクトの並べ替えとフィルタが楽すぎて笑った。
並べ替え用のDatatable作ってたりいったい今まで俺は何をやっていたんだろう‥
2010/06/05(土) 19:57:34
VB脳乙
Listのソートやフィルタは別にLINQやDataTable使わなくても簡単にできる
543デフォルトの名無しさん
垢版 |
2010/06/06(日) 00:08:23
>>542
わざわざそういうクラスを実装した上でLISTを作ればの話だろ?
オブジェクト型のList作って、適当に格納したオブジェクトの対象としたいメンバさえ一致すれば、一行で書けてしまうは凄い。
わかっててやらないと危ういけど‥
2010/06/06(日) 00:18:40
Listにソートmethodつければ良いだけじゃん
2010/06/06(日) 01:05:19
List<T>.Sort()
List<T>.Find()
とかないの?使えないの?
2010/06/06(日) 10:17:56
その二つはVB使いには使い方が理解しづらいメソッドの定番
LINQも同様に高階関数使ってるけどクエリ式で隠してるわけだ
2010/06/06(日) 13:33:23
拡張メソッド形式のLINQのわかりやすさは異常。
2010/06/07(月) 00:43:25
>>546
なるほど
まあC#使いでも foreach(){ if(current==target)...}ってやってるやつもいるな。
2010/06/07(月) 18:47:48
気付いたら>>548スタイルで書こうとしてて拡張メソッドで書き直すことはたまにあるな
あまりにもよく使われるパターンだったから手が覚えてるんだよね
2010/06/10(木) 07:41:28
C#, EF4で、ちょっとハマったので質問させてくれ。
DbContextというのがedmxで定義されたコンテキスト、Hogeというのがedmxで定義されたエンティティ型で、
Piyoがedmxとは関係ないクラスだとする。

「DbContext.Hoge.Select(x => new Piyo() { A = x.A, B = x.B })」

みたいな書き方は普通にできて、普通にIQueriable<Piyo>(実体はObjectQuery<Piyo>)が返ってくるよね。
CreateQueryを使って同じようなことがしたいとき(つまりObjectQuery<Piyo>がほしいとき)
どうすればいいんだろう?

「DbContext.CreateQuery<Piyo>("SELECT VALUE Piyo (x.A, x.B) FROM Hoge AS x")」

こう書くと、「Piyoなんて型見つからない」って怒られるし、かといってE-SQL内でVALUE Piyoを
指定しないと「MaterializedDataRecordからPiyoに変換できない」と怒られるし(当然だけど)。
2010/06/10(木) 14:35:37
名前空間は?
552550
垢版 |
2010/06/10(木) 15:29:40
>>551
Hogeは、型はMyApp.Data.Hoge。EdmEntityTypeAttributeでは「DataModel」が名前空間になってる。
「DataEntities」がエンティティセットの名前空間。
PiyoはMyApp.Something.Piyo。コンストラクタに二つの引数がある。

これを踏まえて
「DbContext.CreateQuery<Piyo>("SELECT VALUE MyApp.Something.Piyo (x.A, x.B) FROM DataEntities.Hoge AS x")」
としてみたけど、だめだった。
553550
垢版 |
2010/06/11(金) 10:16:21
うーん、そもそもCreateQueryってそういう使い方しないのね。
DbDataRecordで受け取るのが一般的なのか。

IQueriableなのに、後からWhereとか追加できない不思議仕様だ。
2010/06/13(日) 14:12:11
ごちゃごちゃ言わずにソース出せ。
555デフォルトの名無しさん
垢版 |
2010/06/15(火) 15:18:45
これ仕事で使ってる人いる?
2010/06/15(火) 20:29:00
OfType()のおかげでArrayListが大復活。

var al = new ArrayList();
al.Add(1);
al.Add(2);
al.Add(3);
al.Add(1D);
al.Add(2D);
al.Add(3D);

var q = al.OfType<double>().Where(n => n >= 2.0);
2010/06/15(火) 20:48:14
大復活って、いやいやw
せめてList<Object>で……。
2010/06/24(木) 02:06:34
ある2つのフォルダ間で同じファイル名かつ更新日時が新しいものをLINQで取得したいです。
IEqualityComparer<FileInfo>を継承したMyCompareを使ってExceptしたのですがうまくいきません。
GetHashCode()で return 1;など定まった値を返せばうまくいくので、GetHashCode()の実装が悪いのかと思います。
しかし、オブジェクトを一意に特定するためのメソッドなのだからそういった実装は間違っていると思います。

もしかしたら全然勘違いをしているかもしれませんが、どなたか助け舟をいただけませんか?
よろしくお願いします。
ソース:http://ideone.com/Ttea4
2010/06/24(木) 04:14:11
比較する際に内部では、最初にGetHashCodeでハッシュコードを取得して、
それが同じ値であったらEqualsで比較する、という動きをします。
なので、GetHashCodeはobj.FullName.GetHashCode()だけ返せばいいんじゃないのかな?
LastWriteTimeまで算出に含めるから希望通りに動かないのでは、と思ってみる。
あと、FullNameじゃそもそも「ファイル名」じゃなくてフルパスを取っちゃうから絶対に一致しない。

でも、なんというか、その用途にExceptは違う気もします。
2010/06/24(木) 04:17:39
マルチ質問にマルチ回答かw
561559
垢版 |
2010/06/24(木) 04:24:52
あー、ほんとだ、C#相談室のほうにも同じ質問投げてあったのね。
しかし回答がまるっきり一緒とは……。
■ このスレッドは過去ログ倉庫に格納されています