VS2008でフォームプロジェクトをつくり、フォームにボタンを設置しハンドラを以下のように書くとエラーになる。
1 2 3 4 5 |
private void button1_Click(object sender, EventArgs e) { Location.X = 100; Location.Y = 100; } |
1 |
エラー 1 変数ではないため、'System.Windows.Forms.Form.Location' の戻り値を変更できません。 C:\T\hhh\nonvariable\nonvariable\Form1.cs 21 13 nonvariable |
再現するために簡単なコンソールプログラムを作る。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; namespace nonvariable2 { class AA { internal System.Drawing.Point pt{get;set;} }; class Program { static void Main(string[] args) { AA aa = new AA(); // エラー 1 変数ではないため、'nonvariable2.AA.pt' の戻り値を変更できません。 // aa.pt.X = 100; Point pp = aa.pt; pp.X = 100; Console.WriteLine(aa.pt.X); } } } |
Form.LocationはSystem.Drawing.Pointでこれはstructであり、value typeだ。
value typeということはボックス化が問題のように感じるがおそらくこれはそうではない。
value typeとはC言語で言うところのstructであって=で値を設定すれば全フィールドコピーされ、関数で渡しても関数から返してもコピーされるような型のことだ。
上記コードのプロパティpt.getはあくまで関数であり返すのはコピーである。ボックス化されたものではない。よってこのコピーの値を変更することは意味を成さない。プロパティにしなければエラーにはならない。
最初のコードは以下のように書くのが正解
1 2 3 4 |
private void button1_Click(object sender, EventArgs e) { Location = new Point(100, 100); } |
Form.Locationはウインドウの位置だからX,Yを別々に設定するのはよくない。しかしエラーの表示は「変数でないため」というのも変な感じだ。これはFormの設計がおかしいのだろうか。
Form.Locationはsetされたときウインドウの位置を変えないとならないのでプロパティでやるしかない。Pointをいじれないとするとしょうがないのか
ちなみにC++/CLIだとエラーにならないが、あたいは設定されないので最初なやむ。