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

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

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

Re[1]: C# 構造体を画面間での渡し方


(過去ログ 140 を表示中)

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

■82103 / inTopicNo.1)  C# 構造体を画面間での渡し方
  
□投稿者/ ピー助 (1回)-(2016/12/11(Sun) 21:00:58)

分類:[C#] 

C# 構造体を画面間での渡し方で、うまく渡せずエラーが出ます。

from1

public struct strNumber
{
public string strNumber1;
public string strNumber2;
public string strNumber3;
public string strNumber4;
public string strNumber5;
}

public partial class from1: Form
{

public strID strNumber { get; set; }

private void btn_Click(object sender, EventArgs e)
{

// 画面表示
using (from from2 = new from2())
{
frm.strID = strID ;
this.Hide();
DialogResult dlgResult = frm.ShowDialog();
//戻り確認。更新されていたら再表示
this.Show();
frm.Dispose();
}
}

}


from2

public partial class from2: Form
{
public strID strNumber { get; set; }

private void from2_Load(object sender, EventArgs e)
{
strID.strNumber1 = "123"; ← 「静的でないフィールド、メソッド、またはプロパティ from2.strIDで、オブジェクト参照が必要です」とエラーが出ます
}
}
}


下記のようなやり方とかも試しましたが、解決できませんでした。
private void from2_Load(object sender, EventArgs e)
{
   strNumber num = new strNumber();
   num = strID;
num.strNumber1 = "123";
}


よろしくお願いします






引用返信 編集キー/
■82104 / inTopicNo.2)  Re[1]: C# 構造体を画面間での渡し方
□投稿者/ Azulean (743回)-(2016/12/11(Sun) 22:18:10)
とりあえず、掲載されている範囲で strID というプロパティは存在しないはずなのでどう直したらいいかは助言しづらいです。
引用返信 編集キー/
■82105 / inTopicNo.3)  Re[2]: C# 構造体を画面間での渡し方
□投稿者/ Jitta (235回)-(2016/12/12(Mon) 09:41:32)
メッセージの通りです。
構造体は値型なので、コピーが作られます。
コピーの内容を変更しても、変更したいものの内容は変わりません。

何故、値型(構造体)を使いますか?
値型でなければならない理由はなんですか?
引用返信 編集キー/
■82106 / inTopicNo.4)  Re[1]: C# 構造体を画面間での渡し方
□投稿者/ furu (84回)-(2016/12/12(Mon) 09:48:22)
No82103 (ピー助 さん) に返信

このソースでは、他にも一杯エラーが出ると思います。

「静的でない…オブジェクト参照が必要です」とエラーが出たやつを
コピペしてください。
引用返信 編集キー/
■82107 / inTopicNo.5)  Re[1]: C# 構造体を画面間での渡し方
□投稿者/ 魔界の仮面弁士 (1007回)-(2016/12/12(Mon) 10:32:19)
No82103 (ピー助 さん) に返信
> C# 構造体を画面間での渡し方で、うまく渡せずエラーが出ます。

コンパイルエラーということでしょうか。


> public struct strNumber
これは、「strNumber 型」な構造体の宣言ですね。

【指摘1】
ちなみに、class や struct あるいは プロパティやメソッドの名前は、
先頭が大文字(PascalCase)で記述するようにし、
変数名は先頭小文字(camelCase) にするのが一般的です。


> from1
> public partial class from1: Form
【指摘2】

「from1」(フロム ワン)ではなく
「Form1」(フォーム ワン)ですよね。
from1 → Form1

新規作成したフォームの既定名も、そうなっているはずなので、
これは掲示板投稿時の転記ミスと捉えて、以下、Form1/Form2 と呼称します。

もしも本当に フロム なスペルを期待していたのであれば、
回答内容を適宜読みかえて下さい。


> public strID strNumber { get; set; }
【問題箇所1】

上記は、「strID 型」を返す「strNumber という名前のプロパティ」の宣言を
意味します。この宣言は意図どおりの物になっていますか?

意図どおりだとしたら、「strID 型」の宣言(class/struct/enum)が
追加で必要ということになります。あるいはそうではなく、
「strNumber 型」を返す「strID プロパティ」を宣言したかったのなら、
public strID strNumber { get; set; } ではなく
public strNumber strID { get; set; } となるべきです。


> private void btn_Click(object sender, EventArgs e)
> {
>   // 画面表示
>   using (from from2 = new from2())
【指摘3】
using (from 〜〜 ではなく
using (Form 〜〜 と書かないと、
コンパイルエラーになってしまいます。

Form 型はあっても、from 型は標準では存在しませんので。
しかし実際には、using (Form 〜〜 と書くのも間違いです。


【問題箇所2】
この場合、本当に記述するべきは、上記いずれでもなく、
 using (var form2 = new Form2())
あるいは
 using (Form2 form2 = new Form2())
となるべきです。理由は下記にあります。


> frm.strID = strID ;
ここで strID の内容を受け渡していますよね。

左辺の strID は、Form2 のメンバー(frm 変数のプロパティ)で
右辺の strID は、Form1 のメンバー(this のプロパティ)を
期待して書かれたコードであろうかと想像します。

この行の記述は間違ってはいないのですが、このままでは
仮に、問題箇所1で述べたプロパティ宣言を直していたとしても、
コンパイルエラーになってしまいます。

というのも、Form 型に strID プロパティは存在しませんので、
左辺の frm.strID が使えないためです。strID プロパティを持つのは、
Form 型ではなく、Form1 型や Form2 型です。

すなわち、先ほど書いたように
 using (Form frm = 〜〜
ではなく、
 using (Form2 frm = 〜〜
でなければ意味がない、という事です。



> this.Hide();
> DialogResult dlgResult = frm.ShowDialog();
> //戻り確認。更新されていたら再表示
> this.Show();
【指摘4】
「戻り確認」というコメントが書かれているにもかかわらず、
戻り値である dlgResult の内容を、(if 文等で)確認し損ねているようです。

実際にはこの後記述する予定なのでしょうし、
今回の問題とは直接関係無いですけれどね。



> frm.Dispose();
【指摘5】

間違いでは無いのですが、今回は using ブロックを用いているため、
明示的に frm.Dispose(); を呼び出す必要はありません。
using ブロックを抜けたところで、そのオブジェクトは
即座に Dispose されるようになっています。


> from2
ここから、フロム ツー、もとい、
Form2 (フォーム ツー)のコードですね。


> public partial class from2: Form
> {
それとも、あえて フロム というスペルにしているのでなければ、
ここも from2 → Form2 ですね。意図的なら直さなくても良いですが。


> public strID strNumber { get; set; }
ここも Form1 と同様、プロパティ名宣言が間違っていますね。
修正方法は 問題箇所1 と同様。



> private void from2_Load(object sender, EventArgs e)
> {
>  strID.strNumber1 = "123"; ← 「静的でないフィールド、メソッド、またはプロパティ from2.strIDで、オブジェクト参照が必要です」とエラーが出ます
> }
【問題箇所3】

う〜ん。本当にそのエラーになりますか?

提示頂いたコードを『public struct strID』に変更すれば
そのようなエラーになりますが、元のコードのままなら、
「現在のコンテキストに 'strID' という名前は存在しません。」
というエラーになりそうなものなのですが。


さておき、この場合の修正手順ですが、
 ・構造体宣言は public struct strNumber { …… }
 ・プロパティ宣言は public strNumber strID { get; set; }
という前提においても、
 strID.strNumber1 = "123";
という記述は行えません。

このプロパティが返す値は、class ではなく struct だからです。


対処案としては幾通りかありますが、ひとまずは
 strNumber current = strID; //現在の this.strID を取得
 current.strNumber1 = "123"; //新しい値に書き換え
 current.strNumber2 = "456"; //新しい値に書き換え
 strID = current; //書き換えた内容を this.strID に再セット
のように、一度変数に受けてから、修正後に再セットするか、
 strID = new strNumber() { strNumber1 = "123", strNumber2 = "456" };
のように、新しい値をまとめてセットすることで対応できます。


> 下記のようなやり方とかも試しましたが、解決できませんでした。
>  strNumber num = new strNumber();
【指摘6】
変数 num を宣言し、それを初期化していますね。
class では無く struct なので、「strNumber num;」だけでも良いですが。


>  num = strID;
上で「new strNumber()」をセットしましたが、それを一度も使うこと無く
this.strID をセットしています。実行上は問題無いですが、これだと
先の代入処理が無意味になってしまいますので、纏めて
 strNumber num = strID;
のように記述するのが良いでしょう。

これは、その num に対して
>  num.strNumber1 = "123";
で新しい値をセットしています。ここまでは間違っていません。
しかし、ここで処理を止めてしまっては、まだ足りません。


【問題箇所3】
strNumber は class ではなく struct ですから、
変数 num を操作したところで、プロパティの内容は変わりません。

編集した変数 num を、再度プロパティに書き戻す作業が必要です。
具体的なコードは、問題箇所2で述べていますね。



…そもそも、何故 struct なのでしょう?
new でインスタンス化してもいるようですし、今回のケースでは
class の方が扱いやすいと思うのですが。
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -