>>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);
なるほど、 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噛ませた と書けばいいんですね。言われてみたら当たり前だった・・・。
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;
ところで、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); } とか。いや本当に便利だわ、これなら。
あ、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' の両辺の式を交換してみてください。」 となり、両辺の式を交換しても同じ、という処で詰まっています。
>>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()); って感じで書いてる。