C#, C♯, C#相談室 Part59

このエントリーをはてなブックマークに追加
952デフォルトの名無しさん:2010/06/26(土) 00:25:16
職業SEだからね。
簡潔さなんて自己満足じゃなく、目で追いやすさ確認しやすさが第一なんよ坊ちゃん。
953デフォルトの名無しさん:2010/06/26(土) 00:28:42
おっと、プロの職業SEの出す例が924というなら問題アリアリだな。
954デフォルトの名無しさん:2010/06/26(土) 00:32:51
かなりねぇ。
見やすさとかいう以前に設計やばそう。
955デフォルトの名無しさん:2010/06/26(土) 00:35:16
>>924は上から目線ぐあいから見て上流のSIerか?
日本に置けるIT業界の癌
956デフォルトの名無しさん:2010/06/26(土) 00:38:30
サンプルとして適当に作った仕様に文句言われてもなwwwwwww
そんなアホな仕様だろうと、ちゃんと実装して実現可能と示したんだから、
文句言われる筋合いはないな。
文句を言えるのは対抗してコード出してきた>>930とかだけ。
反論もコードでお願いしますね、プログラマーに向いているお方。
957デフォルトの名無しさん:2010/06/26(土) 00:39:48
必死ww
958デフォルトの名無しさん:2010/06/26(土) 00:41:00
むしろ、小さなサンプルにこそセンスや実力が問われるんだが。
959デフォルトの名無しさん:2010/06/26(土) 00:42:34
こんなスレでどうでもいいよ
960デフォルトの名無しさん:2010/06/26(土) 00:42:35
ちっとは口動かさないで手を動かしなさいよ。あ、レスも手かwwww
961デフォルトの名無しさん:2010/06/26(土) 02:20:56
>>924
listBox1.Items.AddRange(
 from c in this.Controls
 where
   i is TextBox ||
   ((i is ListBox || i is UserControl) && i.Tag is string) ||
   (i is Label && !(i.Text.EndsWith(":") || ((Label)i).Image != null))
 select i.Name);
962デフォルトの名無しさん:2010/06/26(土) 03:03:04
>>961
x from c in this.Controls
o from i in this.Controls
963デフォルトの名無しさん:2010/06/26(土) 11:19:33
要 .OfType<Control>()
964デフォルトの名無しさん:2010/06/26(土) 11:34:12
なるほど、
var ctrls
= from ctr in Controls.OfType<Control>()
where (
(
ctr is TextBox
) || (
((ctr is ListBox) || (ctr is UserControl))
&& (ctr.Tag is String)
) || (
(ctr is Label)
&& (!((ctr.Text.EndsWith(":") || ((ctr as Label).Image!=null))))
)
)
select ctr.Name;
listBox2.Items.AddRange(ctrls.ToArray());
※ OfType追加と、AddRangeはIEnumrable<String>許容しないんでToArray噛ませた
と書けばいいんですね。言われてみたら当たり前だった・・・。

これなら(個人主観で)納得。簡潔に書きたい場所で使ってみます、ありがとうございました。
965デフォルトの名無しさん:2010/06/26(土) 11:38:17
あ、こう書けばよかった。
listBox2.Items.AddRange((
from ctr in Controls.OfType<Control>()
(where 句省略)
select ctr.Name
).ToArray());
966デフォルトの名無しさん:2010/06/26(土) 13:30:27
家に帰ったら参戦
967デフォルトの名無しさん:2010/06/26(土) 13:41:59
Func<Control, bool> lambda_cond = ctr => (
(
ctr is TextBox
) || (
((ctr is ListBox) || (ctr is UserControl))
&& (ctr.Tag is String)
) || (
(ctr is Label)
&& (!((ctr.Text.EndsWith(":") || ((ctr as Label).Image!=null))))
)
);
と delegate で条件書いて、
foreach (Control ctr in this.Controls) {
if (lambda_cond(ctr)) {
listBox3.Items.Add(ctr.Name);
}
}
と差し替え可能にしてみたんだけど、LINQ 版の書き方がわかんないです。
listBox2.Items.AddRange((from ctr in Controls.OfType<Control>() where lambda_cond select ctr.Name).ToArray());
と書くと「型 'System.Func<System.Windows.Forms.Control,bool>' を型 'bool' に暗黙的に変換できません。」。
どう書いたらいい?単に書き方の問題だと思ってる。
968デフォルトの名無しさん:2010/06/26(土) 13:44:22
天啓キター
listBox2.Items.AddRange((from ctr in Controls.OfType<Control>() where lambda_cond(ctr) select ctr.Name).ToArray());
で自己解決。当たり前だw
969デフォルトの名無しさん:2010/06/26(土) 14:47:25
じゃあ俺はこれで

Func<Control, bool?>[] filter = {
  c => (c is TextBox) ? true : default(bool?),
  c => ((c is ListBox || c is UserControl) && c.Tag is string) ? true : default(bool?),
  c => (c is Label && !c.Text.EndsWith(":") && (((Label)c).Image == null)) ? true : default(bool?),
};

var q = from Control c in Controls
     let qq = from f in filter
          select f(c) into r
          where r != null
          select (bool)r
     where qq.FirstOrDefault()
     select c.Name;

listBox1.Items.AddRange(q.ToArray());
970デフォルトの名無しさん:2010/06/26(土) 15:28:01
判定をor別に配列化してサブクエリでマッチング。
マッチはtrue,アンマッチはnullで結果にnullしかなければfalseとしてtrueを集める。
判定を分割して追加削除をやりやすくしようと言うんですね。
むずかしす・・・でも更新箇所は配列要素になっていて扱いやすそう。
filter をパラメータにして関数化してしまえば隠蔽できるし。
971デフォルトの名無しさん:2010/06/26(土) 15:33:35
ところで、WMIにLINQを適用してみて、こりゃ便利と理解。
Func<string, IEnumerable<ManagementObject>> GetManagementObject
= type => new ManagementClass(type).GetInstances().OfType<ManagementObject>();
foreach (var d in
from ldisk in GetManagementObject("Win32_LogicalDisk")
from l2p in GetManagementObject("Win32_LogicalDiskToPartition")
from d2p in GetManagementObject("Win32_DiskDriveToDiskPartition")
from disk in GetManagementObject("Win32_DiskDrive")
where ldisk.ToString()==l2p["Dependent"].ToString()
&& l2p["Antecedent"].ToString()==d2p["Dependent"].ToString()
&& d2p["Antecedent"].ToString()==disk.ToString()
select new {Name=ldisk["DeviceID"], PNPDeviceID=disk["PNPDeviceID"]
, ldisk, l2p, d2p, disk })
{
Console.Out.WriteLine("{0} : {1}", d.Name, d.PNPDeviceID);
}
とか。いや本当に便利だわ、これなら。

これで、DiskDrive と結びつかない LogicalDisk もリストアップしたいと挑戦中。
outer join とかどう表現したらいいんでしょう?
972デフォルトの名無しさん:2010/06/26(土) 15:39:36
クエリキーワードにはjoinもあるが
973デフォルトの名無しさん:2010/06/26(土) 15:58:34
すみません。正確には、こういう場合での DefaultIfEmpty の使い方です。
974デフォルトの名無しさん:2010/06/26(土) 16:12:31
あ、Win32_LogicalDiskToPartition と関連づかない Win32_LogicalDisk を集めて
Union で混入させてしまえば、というアイデアが浮かんだ。

でも、左外部結合を繰り返すパターンの書き方が知りたいです。
関連づかない場合は l2p, d2p, disk のそれぞれに null が入って返ってくる方法。
今は
foreach (var d in
from ldisk in GetManagementObject("Win32_LogicalDisk")
join l2p in GetManagementObject("Win32_LogicalDiskToPartition")
on ldisk.ToString() equals l2p["Dependent"].ToString()
into ld_l2p from ld_l2p_outer in ld_l2p.DefaultIfEmpty()
join d2p in GetManagementObject("Win32_DiskDriveToDiskPartition")
on l2p["Antecedent"].ToString() equals d2p["Dependent"].ToString()
join disk in GetManagementObject("Win32_DiskDrive")
on d2p["Antecedent"].ToString() equals disk.ToString()
select new {
Name=ldisk["DeviceID"], PNPDeviceID=disk["PNPDeviceID"]
, ldisk, l2p, d2p, disk
})
という感じで on l2p["Antecedent"].ToString() equals d2p["Dependent"].ToString() が
「名前 'l2p' は 'equals' の左辺のスコープにありません。'equals' の両辺の式を交換してみてください。」
となり、両辺の式を交換しても同じ、という処で詰まっています。
975デフォルトの名無しさん:2010/06/26(土) 16:16:16
どうでもいいけど見づらいなぁ。
976デフォルトの名無しさん:2010/06/26(土) 16:21:55
初心者スレには長いコードはideoneに貼れ
というテンプレがあるけど、こっちにはないのね。

そして、964は、なんでわざわざ気持ち悪い改行に改悪するのだか……
これが職業SEの目で追いやすいコード?
977デフォルトの名無しさん:2010/06/26(土) 16:57:50
>>976
修正しやすいコード
978デフォルトの名無しさん:2010/06/26(土) 17:06:04
>>976
>>964 とかは
foreach
  from ... (で元の集合)

  join ... (で結合する集合)
    on ... (で結合条件)
    into ... (で一次的な結合結果集合)

  join ... (で結合する集合)
    on ... (で結合条件)
    into ... (で一次的な結合結果集合)

というように条件を追加削除しやすい単位でまず分けて、かつ横幅がA4印刷に
耐えられる程度で分けてインデントという意図。
何か疑問でも?疑問あるなら改良してくれ。
979デフォルトの名無しさん:2010/06/26(土) 17:09:58
がーーーーーん、974と間違いた!!
けど、考え方は同じ。
縦に伸びすぎない限りは条件の深さ別にインデントしつつ行分けしておいてる。
実際のコードだと更にコメントが入る。
980デフォルトの名無しさん:2010/06/26(土) 17:31:27
>>964 の元々のインデントを全角空白で見え易くすると
var ctrls
  = from ctr in Controls.OfType<Control>()
  where (
    (
      ctr is TextBox
    ) || (
      ((ctr is ListBox) || (ctr is UserControl))
      && (ctr.Tag is String)
    ) || (
      (ctr is Label)
      && (!((ctr.Text.EndsWith(":") || ((ctr as Label).Image!=null))))
    )
  )
  select ctr.Name;
listBox2.Items.AddRange(ctrls.ToArray());
って感じで書いてる。
981デフォルトの名無しさん:2010/06/26(土) 18:08:46
仕事振りにアヤつけられたらなんか、だんだん腹が立ってきた。
仕事でコメントも付けて書くとしたら、こんな感じかな。
    #region 条件に合ったコントロールの名前をコントロール一覧に表示
    var ctrls
        = from ctr in Controls.OfType<Control>()
        // 選択条件
        where (
            (
                // TextBox の場合、無条件
                ctr is TextBox
            ) || (
                // ListBox, UserControl の場合
                ((ctr is ListBox) || (ctr is UserControl))
                // Tag が文字列
                && (ctr.Tag is String)
            ) || (
                // Label の場合
                (ctr is Label)
                // ":" で終わっているか、Image が null でないものは除く
                && (!((ctr.Text.EndsWith(":") || ((ctr as Label).Image!=null))))
            )
        )
        select ctr.Name;
    listBox2.Items.AddRange(ctrls.ToArray());
    #endregion
IDEじゃなく印刷ベースでレビューとかするなら、コメントに●とか目立つ文字を
先頭に入れておくとか別インデントとかすることもある。印刷だとコメントも見づらいから。気分。
ムシャクシャしてやった。今は後悔している。
982デフォルトの名無しさん:2010/06/26(土) 18:23:46
ideoneでやれ
983デフォルトの名無しさん:2010/06/26(土) 18:28:33
ソースのフォーマットとかLINQ使うか否かとか以前にやり方が汚い
修正のしやすさとかいうんだったら、LINQやラムダを使うかどうかはどうでもいいけど
考え方は>>969スタイルにするべき
984デフォルトの名無しさん:2010/06/26(土) 18:33:01
>>981
そのコメント不要だろ。
985デフォルトの名無しさん:2010/06/26(土) 18:41:33
981は
for(){
} // for終わり
とか
string hoge = hage; // hogeにhageを代入
とかかきそうだね。
コメントだらだら入れれば見やすいってもんじゃねーぞ。
そんな小さい部分にregionもいらねえし。
986デフォルトの名無しさん:2010/06/26(土) 19:08:34
ほいほい >>960

WMI で外部結合させる版、とりあえず無理矢理に自己解決させましたけど、
・・・ド汚くて、どうしたらいいかわからないです。どう改良すればよいでしょう?

http://ideone.com/bOJL9
987デフォルトの名無しさん:2010/06/26(土) 20:48:48
>>981
メソッド内でregionで閉じられたソースがあったら
どれだけ長大なソースが展開されるのかと思って怖くて仕方が無いです。
まともな行数のメソッドならregionが必要になることもないわけだし、
メソッド内でregionを使う習慣がある人のソースはどれだけ長大な最長不倒メソッドを日頃から作ってるんだよという感じで怖すぎます。
988デフォルトの名無しさん:2010/06/26(土) 20:49:52
>>987
もしかしたら作業用の画面解像度が低いだけかもしれないぞ
989デフォルトの名無しさん:2010/06/26(土) 22:54:52
ちなみに100行近くなったら関数分割考えるし、それ以前でも共通処理多けりゃ
共通化するよ。ご心配なく。
サンプルってんだろ・・・ほんと >>960
990デフォルトの名無しさん:2010/06/26(土) 23:01:26
ちょい開いてみた。
http://ideone.com/9bOXe
ネストの気持ち悪さは減ったけど共通的な部分多いのが気になってる。
こんなことしなくても join のうまい書き方ってありそうなんだけどなぁ・・・なんとなくの感触だけど。
991デフォルトの名無しさん:2010/06/26(土) 23:51:42
>>989
ほんとセンスの無さに溢れてるな
992デフォルトの名無しさん:2010/06/26(土) 23:55:02
やりすぎて収集つかなくなった・・・一応動作はするけど、あきらかにダメだろー、な見本。
http://ideone.com/Dmtg7

自虐ネタとして。
993デフォルトの名無しさん:2010/06/27(日) 00:00:11
どうせならLINQ to WMI作ってCodeplexで公開しようぜ
994デフォルトの名無しさん:2010/06/27(日) 03:07:12
中途半端はやめて、気の向くままに、開き直って。

ライブラリ
http://ideone.com/OHmUl
使用サンプル
http://ideone.com/hl3Ai

WBEMのイベントとか面倒そうだし、LINQに慣れるために使ってみただけだから
いじくるのは終了〜
どうせ昨日LINQ始めたばかりの初心者だから、もっといい書き方もあるだろうし。
995デフォルトの名無しさん:2010/06/27(日) 03:15:46
>>969
さん、貴重なご示唆ありがとうございました。
まだ勉強しないと使いこなせないようですが。


ところで、次スレ建ててくるね。特にテンプレはつけないからよろしく。
996デフォルトの名無しさん:2010/06/27(日) 03:17:56
建てました。

C#, C♯, C#相談室 Part60
http://pc12.2ch.net/test/read.cgi/tech/1277576240/
997デフォルトの名無しさん:2010/06/27(日) 07:21:53
>>989
100行をある程度の目安にするところは同意だが、メソッド内でregionはないな。
fold機能を覚えたての初心者がよく乱発する
998デフォルトの名無しさん:2010/06/27(日) 10:32:17
#region プライベートフィールド
#endregion

#region コンストラクタ
#endregion

みたいな見りゃわかるよ系はどうよ
999デフォルトの名無しさん:2010/06/27(日) 10:37:06
別にコメントの代わりに使ってるわけじゃないだろ
コンストラクタやプロパティは畳んでおきたくなるのはわかる
1000デフォルトの名無しさん:2010/06/27(日) 10:56:28
オーバーロード単位で畳む人もいたな
10011001
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。