C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[10]: foreachを使わない


(過去ログ 120 を表示中)

[トピック内 19 記事 (1 - 19 表示)]  << 0 >>

■70333 / inTopicNo.1)  foreachを使わない
  
□投稿者/ まさおっち (1回)-(2014/03/12(Wed) 21:40:30)

分類:[.NET 全般] 

foreachを使わずに今やっている処理ができるか知りたいです。

やっている処理は、

foreach (var s in _tool)
{
var title=s.name;
}

_toolには、DLLから集めてきた情報、name(プロパティ渡し)やメソッドが入っています。

この処理、foreachを使っていますが1度しかループしていないので、ほかの方法もないかと思いまして・・・

引用返信 編集キー/
■70334 / inTopicNo.2)  Re[1]: foreachを使わない
□投稿者/ まさおっち (2回)-(2014/03/12(Wed) 22:08:18)
なんか説明不足なので追記します。

foreach以外でコレクションの内の1つを変数(s)に入れる方法はないだろうか!?
ということです。


引用返信 編集キー/
■70335 / inTopicNo.3)  Re[2]: foreachを使わない
□投稿者/ Azulean (281回)-(2014/03/12(Wed) 22:44:26)
2014/03/12(Wed) 22:45:22 編集(投稿者)

No70334 (まさおっち さん) に返信
> foreach以外でコレクションの内の1つを変数(s)に入れる方法はないだろうか!?
> ということです。

・LINQ の First を使う
・IEnumerable なのであれば GetEnumerator で IEnumerator を取得して MoveNext して Current を取得する
・配列・リスト・コレクションなら _tool[0] とする。

いずれも 0 個があり得る場合は注意。

-----
そうではなく、コレクション内のあるプロパティ(string)の集合に変換したい場合は LINQ の Select を使うとよいかも。
引用返信 編集キー/
■70336 / inTopicNo.4)  Re[1]: foreachを使わない
□投稿者/ shu (507回)-(2014/03/13(Thu) 00:40:04)
No70333 (まさおっち さん) に返信
>
> この処理、foreachを使っていますが1度しかループしていないので、ほかの方法もないかと思いまして・・・
>
実際に2回以上のループをどのように実装されて何が問題なのでしょうか?


> foreach (var s in _tool)
> {
> var title=s.name;
> }
この処理は結果的に何もしないのと変わりないのですがどういう目的でループさせているのでしょうか?
引用返信 編集キー/
■70337 / inTopicNo.5)  Re[2]: foreachを使わない
□投稿者/ まさおっち (3回)-(2014/03/13(Thu) 07:26:56)
> 実際に2回以上のループをどのように実装されて何が問題なのでしょうか?
ループの中でボタンを作成し、そのボタンにDLLで拾ってきた関数がひもづけられているのですが、
1周目で作成されたボタンと2周目で作成されたボタンに割り当てられる関数が同じになってしまって困ってます。
s.nameがt.nameとそれぞれ別の変数であればこのようなことは起きないはずだという考え方から、foreach以外の方法を探し始めました。







>>foreach (var s in _tool)
>>{
>> var title=s.name;
>>}
> この処理は結果的に何もしないのと変わりないのですがどういう目的でループさせているのでしょうか?
これは、うまくいかなかった今までのやり方の残りです。


引用返信 編集キー/
■70338 / inTopicNo.6)  Re[3]: foreachを使わない
□投稿者/ 魔界の仮面弁士 (557回)-(2014/03/13(Thu) 10:30:34)
2014/03/13(Thu) 14:04:42 編集(投稿者)

# 投稿モードを図表モードにし忘れたので、コードのインデントが
# 崩れてしまいました…全角空白でインデントしておきます。

No70333 (まさおっち さん) に返信
> この処理、foreachを使っていますが1度しかループしていないので、ほかの方法もないかと思いまして・・・
Array.ForEach メソッドとか、List<T>.ForEach メソッドとか?


No70334 (まさおっち さん) に返信
> foreach以外でコレクションの内の1つを変数(s)に入れる方法はないだろうか!?
最初の一個を取得するだけで良いのなら、
 var s = _tool.FirstOrDefault();
と書くことができます。

特定の一要素ではなく、すべてを個別に取り出して
処理していきたいというのであれば、単純に foreach で
十分かと思いますが、どうしても foreach が嫌なのであれば、
Azulean さんが No70335 で示された方法などがありますね。



No70337 (まさおっち さん) に返信
>>> foreach (var s in _tool)
>>> {
>>> var title=s.name;
>>> }
>
> s.nameがt.nameとそれぞれ別の変数であれば
>
ここでいう s と t は、それぞれ何を意味しているのでしょうか?
s については記載がありましたが、t についての説明が無いようです。

変数の名前からして、
 s = _tool[0];
 t = _tool[1];
 u = _tool[2];
 v = _tool[3];
 w = _tool[4];
のようなイメージでなのでしょうか。
(_tool にインデクサがあるかどうかは別として)



>>実際に2回以上のループをどのように実装されて何が問題なのでしょうか?
> ループの中でボタンを作成し、そのボタンにDLLで拾ってきた関数がひもづけられているのですが、
> 1周目で作成されたボタンと2周目で作成されたボタンに割り当てられる関数が同じになってしまって困ってます。

「DLLで関数を拾う」というのが良く分からず、
状況がまだ朧げにしか見えてこないのですが、現在は

// 同じ処理を割り当てる例
foreach(var s in _tool)
{
 var btn = new Button() { Text = s.Name, Location = s.Position, Tag = s.Id };
 Controls.Add(btn); // ループの中でボタンを作成し
 btn.Click += dllFunctionEventHandler; // DLL関連の関数を紐付け
}

に相当する処理を行っているのでしょうか。


> ボタンに割り当てられる関数が同じになってしまって困ってます。
「ボタンに割り当てられる関数」というのは、上記のように Click イベントに対する
イベントハンドラの割り当てという意味でよろしいでしょうか。

そうだとして、「同じ」になってしまうのが困る、という話については:

どちらのボタンが押されたのかが分からなくなる、という意図であれば
sender 引数で判定できますし、個別情報を渡しておきたいなら Tag を使う手もあります。
あるいは、それぞれのボタンごとに別の処理を割り当てたいのなら、
ボタン1用の処理、ボタン2用の処理をそれぞれ分けて準備しておいて、
それらを個別に割り当てていけば良いかと思います。


以下、参考例:


//----- 案1:同じ処理を割り当てておき、イベントハンドラ内で判定する -----

// Click 時に処理させたい内容
void dllFunctionEventHandler(object sender, EventArgs e) {
 // 実際は if や switch などで分岐するなど
 var button = (Button)sender;
 MessageBox.Show(button.Tag as string, button.Text);
}

private void button1_Click(object sender, EventArgs e) {
 
 var _tool = new[] {
  new {Name = "A", Position = new Point(1, 10), Id = "100"},
  new {Name = "B", Position = new Point(1, 50), Id = "200"},
  new {Name = "C", Position = new Point(1, 90), Id = "300"}
 };

 foreach (var item in collection) {
  var btn = new Button() { Text = item.Name, Location = item.Position, Tag = item.Id };
  Controls.Add(btn); // ループの中でボタンを作成し
  btn.Click += new EventHandler(dllFunctionEventHandler); // DLL関連の関数を紐付け
 }
}


//----- 案2:ボタンごとに異なる処理を割り当てる -----
private void button1_Click(object sender, EventArgs e)
{
 var collection = new[] {
  new {Name = "開く", Position = new Point(1, 10), Proc = new EventHandler(delegate { MessageBox.Show("A"); })}, // 匿名メソッド(引数省略)
  new {Name = "終了", Position = new Point(1, 50), Proc = new EventHandler(delegate(object o, EventArgs a) {this.Close();})}, // 匿名メソッド(引数あり)
  new {Name = "隠す", Position = new Point(1, 90), Proc = new EventHandler((o, a) => ((Control)o).Hide())}, // ラムダ式
  new {Name = "呼ぶ", Position = new Point(1,130), Proc = new EventHandler(dllFunctionEventHandler)}, // デリゲートインスタンス
 };

 foreach (var item in collection) {
  var btn = new Button() { Text = item.Name, Location = item.Position };
  Controls.Add(btn);
  btn.Click += item.Proc;
 }
}
引用返信 編集キー/
■70350 / inTopicNo.7)  Re[4]: foreachを使わない
□投稿者/ まさおっち (5回)-(2014/03/14(Fri) 13:00:50)
返信ありがとうございます。返事が遅くなってしまってすみません。

>>変数の名前からして、
>> s = _tool[0];
>> t = _tool[1];
>> u = _tool[2];
>> v = _tool[3];
>> w = _tool[4];
>>のようなイメージでなのでしょうか。

ズバリそのようなイメージです。




>>「DLLで関数を拾う」というのが良く分からず、
>>状況がまだ朧げにしか見えてこないのですが、

問題が発生している部分だけの機能で作り直してみました。

http://1drv.ms/1nXI0l1

ファイルにチェックを入れて上のダウンロードを押すとダウンロードできます。


>>イベントハンドラの割り当てという意味でよろしいでしょうか。
そのような意味です。



教えてくださった方法本日確かめてみます。よろしくおねがいします。

引用返信 編集キー/
■70355 / inTopicNo.8)  Re[5]: foreachを使わない
□投稿者/ まさおっち (6回)-(2014/03/14(Fri) 19:30:17)
DLするのは大変だと思いますので、ソースを記述しておきます。

//form1
        public void CreateNewTab()
        {
            if (_message == null) return; //インターフェイスは何か読めてるか?
            foreach (var item1 in _message)
            {
                if (ブログ数 != 0) { break; } //タブを無限増殖させないため
                // tabの追加
                var title = item1.TabName;
                var tabPage = new TabPage(title);
                tabPage.BackColor = Color.White;
                tabPage.Name = "tab1";
                foreach (var item1 in _message)
                {
                    ブログ数 = ブログ数 + 1;
                    アイコンの位置 = (ブログ数 - 1) * 13;
                    var PictureBox1 = new PictureBox();
                    PictureBox1.Location = new System.Drawing.Point(10 * アイコンの位置 + 10 + ブログ数, 10); //
                    PictureBox1.Size = new System.Drawing.Size(120, 120);
                    PictureBox1.ImageLocation = item1.picturebox1url();
                    PictureBox1.Click += (s, e) =>
                    {
                        removeDynamicControls("blogtextbox1");
                        removeDynamicControls("blogbutton");
                        item1.DLL関数(this.tabControl1, this.Controls);
                    };
                    tabPage.Controls.Add(PictureBox1);
                }
                tabControl1.TabPages.Add(tabPage); //タブ作成
            }
        }
        //テキストボックスなどを名前指定で消す。
        public void removeDynamicControls(string textbox)
        {
            Control[] controls = Controls.Find(textbox, true);
            foreach (Control control in controls)
            {
                this.Controls.Remove(control);
                control.Dispose();
            }
        }
------------------------------------------------------------------------------------------------------------------------------------------------
//DLL1
            public void DLL関数(TabControl tabControl1, Control.ControlCollection Controls)
            {
                Form1 form1;//Formクラスのインスタンス化。
                form1 = new Form1();
                //テキストボックス1
                var blogtextbox1 = new TextBox();
                blogtextbox1.Location = new System.Drawing.Point(10, 30);//
                blogtextbox1.Size = new System.Drawing.Size(180, 10);
                blogtextbox1.Name = "blogtextbox1";
                Controls.Add(blogtextbox1);
                //ボタン
                var blogbutton2 = new Button();
                blogbutton2.Location = new System.Drawing.Point(10, 10);
                blogbutton2.Name = "blogbutton";
                blogbutton2.Size = new System.Drawing.Size(80, 20);
                blogbutton2.Text = "DLL1";
                blogbutton2.Click += (a, b) =>
                {
                    blogtextbox1.Text = "DLL1";
                };
                Controls.Add(blogbutton2);
            }

----------------------------------------------------------------------------------------------------------
//DLL2

           public void DLL関数(TabControl tabControl1, Control.ControlCollection Controls)
            {
                Form1 form1;//Formクラスのインスタンス化。
                form1 = new Form1();
                //テキストボックス1
                var blogtextbox1 = new TextBox();
                blogtextbox1.Location = new System.Drawing.Point(10, 30);//
                blogtextbox1.Size = new System.Drawing.Size(180, 10);
                blogtextbox1.Name = "blogtextbox1";
                Controls.Add(blogtextbox1);
                //ボタン
                var blogbutton2 = new Button();
                blogbutton2.Location = new System.Drawing.Point(50, 10);
                blogbutton2.Name = "blogbutton";
                blogbutton2.Size = new System.Drawing.Size(80, 20);
                blogbutton2.Text = "DLL2";
                blogbutton2.Click += (c, d) =>
                {
                    blogtextbox1.Text = "DLL2";
                };
                Controls.Add(blogbutton2);
            }










このような形になっています。
結果2つのピクチャーボックスができ、押すとボタンが生成されるのですが、ピクチャーボックスは正しく2種のものが出るのに、ピクチャーボックスを押すと両方ともDLL2が出てしまいます。

なぜDLL1のDLL関数をつかうことができないのでしょうか?

引用返信 編集キー/
■70356 / inTopicNo.9)  Re[6]: foreachを使わない
□投稿者/ 魔界の仮面弁士 (561回)-(2014/03/14(Fri) 20:46:59)
No70355 (まさおっち さん) に返信
> DLするのは大変だと思いますので、ソースを記述しておきます。

OneDrive のソリューションを試してみたところ、下記の動作となりました。
動作上は、特に問題点は感じませんでしたが、これは
まさおっちさんが望んでいる結果ではないのですね?


(1) TabControl のみのフォームが表示される。
 タブは、[tabPage1] と[ブログ]の2枚。

(2)[ブログ]タブをクリックすると、タブの中に
 大きく「1」「2」という文字が表示される。

(3)タブ内の「2」をクリックすると、フォーム上部に
 [DLL2]ボタンと TextBox が表示される。
 [DLL2]ボタンを押すと、TextBox には "DLL2" と書き込まれる。

(4)タブ内の「1」をクリックすると、フォーム上部に
 [DLL1]ボタンと TextBox が表示される。
 [DLL1]ボタンを押すと、TextBox には "DLL1" と書き込まれる。


> ピクチャーボックスは正しく2種のものが出るのに、ピクチャーボックスを押すと両方ともDLL2が出てしまいます。
その現象は再現できませんでした。
開発環境は Visual Studio 2012 Update 4、OS は Win7x64 Pro SP1 です。
引用返信 編集キー/
■70357 / inTopicNo.10)  Re[7]: foreachを使わない
□投稿者/ まさおっち (8回)-(2014/03/14(Fri) 21:03:58)
驚きました。
僕の環境は
windows8
Visual Studioの2010・2012・2013
3つで試し、すべてで両方のボタンでDLL2が表示されてしまいます。

動画で僕の画面を作成しました。
http://youtu.be/LMcpGo3OWPE

このようにはなりませんか?


引用返信 編集キー/
■70358 / inTopicNo.11)  Re[8]: foreachを使わない
□投稿者/ Azulean (282回)-(2014/03/15(Sat) 07:23:38)
2014/03/15(Sat) 07:43:13 編集(投稿者)

IL を見ると、添付されている exe は下記のタイミングでラムダの内部実装であるオブジェクトを作っています。

 IL_0062: newobj instance void WindowsFormsApplication1.Form1/'<>c__DisplayClass2'::.ctor()
 IL_0067: stloc.s 'CS$<>8__locals3'

そして、IL0076 近辺でそのオブジェクトに foreach の変数の値が代入されています。

 IL_0076: ldloc.s 'CS$<>8__locals3'
 IL_0078: ldloca.s CS$5$0001
 IL_007a: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class [ClassLibrary1]WindowsFormsApplication1.'インターフェイス'>::get_Current()
 IL_007f: stfld class [ClassLibrary1]WindowsFormsApplication1.'インターフェイス' WindowsFormsApplication1.Form1/'<>c__DisplayClass2'::item1

foreach の繰り返し判定は IL_0125 で行われていますが、飛び先が IL_0076 なので同じオブジェクトを使い回しているようです。

 IL_0120: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class [ClassLibrary1]WindowsFormsApplication1.'インターフェイス'>::MoveNext()
 IL_0125: brtrue IL_0076
 IL_012a: leave.s IL_013a
引用返信 編集キー/
■70359 / inTopicNo.12)  Re[9]: foreachを使わない
□投稿者/ Azulean (283回)-(2014/03/15(Sat) 07:27:08)
2014/03/15(Sat) 07:33:25 編集(投稿者)
2013 Debug/Release の差では起きませんね。
2010 Debug/Mixed Platform では発生しました。

item1 を別のローカル変数に代入してそれを使うようにすれば回避できるかと。

foreach (var item1 in _message)
{
    var item2 = item1;
(略)
     PictureBox1.Click += (s, e) =>
     {
         removeDynamicControls("blogtextbox1");
         removeDynamicControls("blogbutton");
         item2.DLL関数(this.tabControl1, this.Controls);
     };


基本的にループ変数をラムダで使うと期待しないような挙動を示すことがあるので避けた方がよいでしょう。

引用返信 編集キー/
■70361 / inTopicNo.13)  Re[10]: foreachを使わない
□投稿者/ まさおっち (10回)-(2014/03/15(Sat) 12:09:53)
すごい!
var item2 = item1;
に置き換えたただけで正常に動くようになりました!

CILは僕の知識ではおぼろげにしかわからないので理由がよくわかりませんが、とにかく正常に動きました!

心配なので、もうすこし崩して説明していただけませんか?
たとえば、
PictureBox1.ImageLocation = item1.picturebox1url();

PictureBox1.ImageLocation = item2.picturebox1url();
のほうがいいのでしょうか?
引用返信 編集キー/
■70362 / inTopicNo.14)  Re[9]: foreachを使わない
□投稿者/ 魔界の仮面弁士 (562回)-(2014/03/15(Sat) 12:56:12)
No70358 (Azulean さん) に返信
手元の環境では、bin/Debug と bin/Relese で結果が異なっていました。
当方の Debug 版のみ、DLL1/DLL2 と別々に動作していたようです。
Relese版については、他の方が仰られている結果になっていることを確認しました。


CreateNewTab メソッド内の実装を比較したところ、
  foreach (var item in _message)
  {
      if (ブログ数 != 0) { break; }
      /* 中略 */
      foreach (var item1 in _message)
      {
という部分のコンパイル結果が、以下のように異なっていました。


=======================================================
【Release版】常に DLL2 が表示されてしまうパターン
-------------------------------------------------------
  using (List<インターフェイス>.Enumerator enumerator2 = this._message.GetEnumerator())
  {
    if (this.ブログ数 != 0) break;
    /* 中略 */
    インターフェイス item1;
    while (enumerator2.MoveNext())
    {
      item1 = enumerator2.Current;


=======================================================
【Debug版】DLL1 / DLL2 とがそれぞれ表示されるパターン
-------------------------------------------------------
  foreach (インターフェイス インターフェイス in this._message)
  {
    if (this.ブログ数 != 0) break;
    /* 中略 */
    using (List<インターフェイス>.Enumerator enumerator2 = this._message.GetEnumerator())
    {
      while (enumerator2.MoveNext())
      {
        インターフェイス item1 = enumerator2.Current;


ちなみに、ローカル変数の数にも違いがありました。

【Release版】常に DLL2 が表示されてしまうパターン
    .locals init (
        [0] class [ClassLibrary1]WindowsFormsApplication1.インターフェイス インターフェイス,
        [1] string str,       // get TabName() を格納するための一時変数
        [2] class [System.Windows.Forms]System.Windows.Forms.TabPage page,
        [3] class [System.Windows.Forms]System.Windows.Forms.PictureBox box,
        [4] class [mscorlib]System.EventHandler handler,
        [5] class WindowsFormsApplication1.Form1/<>c__DisplayClass2 class2,
        [6] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator`0<class [ClassLibrary1]WindowsFormsApplication1.インターフェイス> enumerator,
        [7] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator`0<class [ClassLibrary1]WindowsFormsApplication1.インターフェイス> enumerator2)

【Debug版】DLL1 / DLL2 とがそれぞれ表示されるパターン
    .locals init (
        [0] class [ClassLibrary1]WindowsFormsApplication1.インターフェイス インターフェイス,
        [1] string str,       // get TabName() を格納するための一時変数
        [2] class [System.Windows.Forms]System.Windows.Forms.TabPage page,
        [3] string str2,      // picturebox1url() を格納するための一時変数
        [4] class [System.Windows.Forms]System.Windows.Forms.PictureBox box,
        [5] class [mscorlib]System.EventHandler handler,
        [6] class WindowsFormsApplication1.Form1/<>c__DisplayClass2 class2,
        [7] bool flag,        // bool 判定用の一時変数
        [8] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator`0<class [ClassLibrary1]WindowsFormsApplication1.インターフェイス> enumerator,
        [9] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator`0<class [ClassLibrary1]WindowsFormsApplication1.インターフェイス> enumerator2)



> foreach の繰り返し判定は IL_0125 で行われていますが、飛び先が IL_0076 なので同じオブジェクトを使い回しているようです。
ここでも若干の違いが出ていました。
List<T>.Enumerator::MoveNext() の結果を直接判定するのではなく、
なぜか bool 型のローカル変数に蓄えてから判定していました。

【Release版】
    L_0120: call instance bool [mscorlib]System.Collections.Generic.List`1/Enumerator`0<class [ClassLibrary1]WindowsFormsApplication1.インターフェイス>::MoveNext()
    L_0125: brtrue L_0076   // MoveNext の戻り値が非ゼロだった場合、0x0076 にジャンプする
    L_012a: leave.s L_013a  //(MoveNext の戻り値がゼロだった場合に)コード保護領域を終了して、0x013a にジャンプする
【Debug版】
    L_014d: call instance bool [mscorlib]System.Collections.Generic.List`1/Enumerator`0<class [ClassLibrary1]WindowsFormsApplication1.インターフェイス>::MoveNext()
    L_0152: stloc.s flag    // スタックからMoveNextの戻り値をポップし、ローカル変数 flag に格納する
    L_0154: ldloc.s flag    // ローカル変数 flag をスタックに読み込む
    L_0156: brtrue L_0082   // flag の値が非ゼロだった場合、0x0082 にジャンプする
    L_015b: leave.s L_016c  //(flag の値がゼロだった場合に)コード保護領域を終了して、0x016c にジャンプする

このflag変数は、!= null 判定の結果の一時保存にも使われていました。

引用返信 編集キー/
■70363 / inTopicNo.15)  Re[11]: foreachを使わない
□投稿者/ 魔界の仮面弁士 (563回)-(2014/03/15(Sat) 13:13:22)
No70361 (まさおっち さん) に返信
> 理由がよくわかりませんが、とにかく正常に動きました!

ラムダ式の中で使われている変数が、いつ評価されるかが問題になります。


> PictureBox1.ImageLocation = item1.picturebox1url();
> は
> PictureBox1.ImageLocation = item2.picturebox1url();
> のほうがいいのでしょうか?

実験コード:


string[] sites = { "yahoo!", "google", "bing" };

var cw1 = new List<Action>();
var cw2 = new List<Action>();
foreach (var site1 in sites)
{
    cw1.Add(() => Console.WriteLine(site1));
    var site2 = site1;
    cw2.Add(() => Console.WriteLine(site2));
}

Console.WriteLine("パターン1");
cw1.ForEach(act => act());

Console.WriteLine("パターン2");
cw2.ForEach(act => act());

引用返信 編集キー/
■70364 / inTopicNo.16)  Re[12]: foreachを使わない
□投稿者/ 魔界の仮面弁士 (564回)-(2014/03/15(Sat) 13:23:32)
No70363 (魔界の仮面弁士) に追記
>>理由がよくわかりませんが、とにかく正常に動きました!
> ラムダ式の中で使われている変数が、いつ評価されるかが問題になります。

ちなみに、こうしたコードを Visual Basic で実装した場合、
コンパイラが警告を発するようになっています。


// C#2010 (警告なし)
  var ary = new Func<int>[5];
  for (int i = 0; i < ary.Length; i++)
  {
      ary[i] = () => i;   
  }
  foreach (var item in ary)
  {
      Console.WriteLine(item());
  }



' VB2010 (警告あり)
  Dim ary1(4) As Func(Of Integer)
  For i = 0 To ary1.GetUpperBound(0)
      ary1(i) = Function() i
  Next
  For Each item In ary1
      Console.WriteLine(item())
  Next


警告 BC42324 http://msdn.microsoft.com/ja-jp/library/bb763133.aspx
 ラムダ式内で繰り返し変数を使用すると、予期しない結果が発生する可能性があります。
 代わりに、ループ内にローカル変数を作成して繰り返し変数の値を割り当ててください。

引用返信 編集キー/
■70365 / inTopicNo.17)  Re[8]: foreachを使わない
□投稿者/ 魔界の仮面弁士 (565回)-(2014/03/15(Sat) 13:45:28)
No70357 (まさおっち さん) に返信
> windows8
> Visual Studioの2010・2012・2013
> 3つで試し、すべてで両方のボタンでDLL2が表示されてしまいます。

この foreach のコンパイル結果については、仕様変更があったはずです。
今調べたら、C#4.0(2010) → C#5.0(2012) のタイミングだったようですね。

http://msdn.microsoft.com/ja-jp/library/vstudio/hh678682%28vs.110%29.aspx
http://ufcpp.net/study/csharp/ap_ver5.html#foreach


なので今回のように、同じバージョン内でも Debug/Release で結果が異なるとか、
同じVSバージョンでコンパイルしても結果が異なるという点には、正直驚いています。
引用返信 編集キー/
■70366 / inTopicNo.18)  Re[9]: foreachを使わない
□投稿者/ Azulean (284回)-(2014/03/15(Sat) 20:33:45)
2010 〜 2013 で同様に再現するというレポートは、2010 でビルドした状態に対して 2012,2013 で単に「開始」ボタンを押して検証したからでしょうか?
開始ボタンを押すだけではビルドし直されないので、すべてのバージョンで再現することになります。
手元でも 2010 で現象を起こしてから、2012, 2013 とバージョンを変えて開いて開始ボタンを押すだけだと再現しました。(ビルドされなかったため)

ただ、手元の 2012 では Release でも再現しませんでした。
2013(か、.NET 4.5)インストールによって内部的な挙動が変化しているのかもしれません。
(その割には同じ csc.exe を使っているように見えるのに振る舞いは違うので MSBuild がいろいろとやっているのかもしれませんが)
引用返信 編集キー/
■70370 / inTopicNo.19)  Re[10]: foreachを使わない
□投稿者/ まさおっち (11回)-(2014/03/16(Sun) 18:25:02)
難しいですが、verの違いはちゃんとしないといけないということですね。
勉強になりました。

ありがとうございます。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -