アクセスランキング C# スコープとフィールド変数|Form間の変数のやり取りとプロパティ - スポンサー広告挫折した人のためのC#講座

直列つなぎ。 -とある発達障害者の記録

知識と知識を繋ぐためのblog。 広汎性発達と診断されました。ぜんぜん役に立ってないけど。月収13万円(うち手取り11万)、家賃4万円で生活するひつじ人間。モウマンタイ。

  

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

 スポンサー広告

   

C# スコープとフィールド変数|Form間の変数のやり取りとプロパティ

ブログパーツ 
 思うところあって、改めて拍手ボタンを付けることにしました。たまには拍手を貰えるとうれしいです。
 18 1.23 コードの書き忘れ修正

 前項 C# メソッドのオーバーロード・オーバーライド

 この項の習得時間は30分とします。それほど難しくないと思います。

 さて、前項まででは、メソッド・戻り値・クラス・オーバーライド・オーバーロードについての直感的な解説を行いました。
 この項では主におさらいをしておきます。
 
 参考 連載! とことん C#: 第 5 回 フィールド (メンバ変数) とプロパティはここが違う

 
  クラス
  class クラス1
           {
             //メンバー変数
          int a;
          string 文字;
 
 //戻り値なし
    void メソッド1(int 引数)
          { //何らかの処理}

     int
           }
 
      int メソッド2()
      {
        int i;
        //何らかの処理,数値を返す
  
     return i;
     }        
  }



 イベント内等で
 クラスの呼び出し方 

  private void button1_Click(object sender, EventArgs e)
        {       
 クラス1 変数名 = New クラス1();
 変数名.メソッド1(引数が必要な場合は引数を入れる);
   }

 この{}内をC#ではスコープと呼びます。
スコープはしばしば、for文やif文等の処理により、入れ子(ネスト)になります。分かり易いように、インデント(空白)を入れるのがいいでしょう。
 


スコープと変数のアクセス

 
 reference:[雑記] 識別子のスコープとオブジェクトの寿命

 以下サンプル(ダブルクリックをするとコードを全選択出来ます)

 

    int[] b = { 1, 2, 3, 4, 5, 6 };
  /*外側がフィールド変数で、WindowsFormsクラスのメンバー変数でもある
  int[] と型に[]を付ける変数を配列と言います。 */    

        private void button1_Click(object sender, EventArgs e)
        {
            int a = b.Length; //bの要素数を取得
    /*  int[] b = { 1, 2, 3, 4, 5, 6 };イベント内で宣言していると、実行の度に
この値に戻ってしまう。*/


            if ( a > 0) //aが0より大きい場合
              {
                string[] c = {"a","b","c","d","e","f" };
// if文内のスコープ上の変数

                for (int i = 0; i < a; i++)
                {// for文内のスコープ
                     
                    Console.WriteLine(b[i]++);
                     //配列内の要素を1ずつ足す これをインクリメント(++)と言います。
                }

                Console.WriteLine("\n");
            }
        }

 出力結果
  出力結果



 このような形ですね。クラスも入れ子に出来ます。
if文、for文については基本的なサイトで十分学べると思いますので割愛。気が向いたら解説します。

 上記の例では、変数 int[] bは、イベントハンドラ内のどのスコープからでもアクセス出来ます。これは、イベントハンドラの外側に出されたフィールド変数だからです(インスタンス化したクラスが持つ変数:インスタンスメンバーとも言います)。


 このように外側にフィールド変数として出しておかないと、イベントを呼ぶごとに変数が初期化されてしまいます。


 では、イベントハンドラ内の一番外側のスコープから、後の行のif文内で宣言された   string[] c にアクセス出来るのでしょうか。

 スコープとアクセス
 
 このように「現在のコンテキストに’c’という名前は存在しません」というerrorが表示されたと思います。 上層のスコープから下層のスコープへはアクセス出来ない訳ですね。  ちなみに、スコープ内の変数にpublic等のアクセス修飾子を付けることは出来ません。

 また、メソッド内で宣言された変数は、そのスコープ内でのみアクセス可能です。


 これで、スコープについての解説が終わりました。
 なお、アクセス修飾子に関してもスコープと呼ばれるようです。


 今度はインスタンス(new演算子)について解説していきたいと思います。
 インスタンスはオブジェクト(Form等)の実態であり、クラスの実態です。



インスタンスとフィールド変数

  
 Form間の変数のやり取りについて考えてみます。ここはしばしば初学者が悩むところでしょう。
通常、検索すると下記の記事がヒットすると思います。
 別のフォームのデータを取得、設定する

 ここでは、dobon.netの説明をもう少し分かり易く解説してみます。
まず、Visual Studioのソリューションエクスプローラー上の名前空間(WindowsFomsApps1等)で右クリックメニューを出して、「追加」→「新しい項目」から「Windows フォーム」を選択してください。2つ目のFormが作成されます。

  

 各フォームを以下のように配置してください。
 
新しい項目 Form1の配置 Form2の配置
1.ソリューションエクスプローラーで、「WindowsFormsApp(名前空間)」上カーソルを合わせて右クリック
2.「新しい項目」から新しいFormを追加してください
Form1の配置です
Form2の配置です。
 

 下記 簡単なコード例 ※dobon.netのものとは変えてあります。

Form1クラス
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
 
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

    
    
        Form2 form2; //イベント間で共有するためのForm2クラス変数

        private void button1_Click(object sender, EventArgs e)
        {
            form2 = new Form2(); //new 演算子によるインスタンス化。
            form2.Show();  //Form2を表示させる。
        }
       

        private void button2_Click(object sender, EventArgs e)
        {      
            Form2.Form2Instance = form2; 
 //Form2のインスタンスにnew(インスタンス化)されたform2を代入 


            textBox1.Text =  Form2.Form2Instance.TextBoxText + "@-ᴥ-@";
        }


    }


Form2クラス ------------------------------------------
  
 public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }
   

      /* Form2オブジェクトを取得、設定するためのプロパティ
         (これは自動実装プロパティです)。*/
         public static Form2 Form2Instance { get; set; }

/* textBox用のプロパティ コントロール(textBox1)を指定するには、
プロパティでスコープ内に入れる必要がある*/
        public string TextBoxText
        {
            get
            {
                return textBox1.Text;
            }
            set
            {
                textBox1.Text = value;
            }
        }   

        private void Form2_Load(object sender, EventArgs e)
        {
            textBox1.Text = "Form2のテキスト";
        }
  }
    

 
 dobon.netでは
//Form1オブジェクトを保持するためのフィールド
  private static Form1 _form1Instance;

 がありましたが、このサンプルでは省いてあります。dobon.net様のものと全く同じ動作をすると思いますので確認してみてください。



 プロパティとは
    reference: http://ufcpp.net/study/csharp/oo_property.html
    > クラス外部から見るとメンバー変数のように振る舞い、 クラス内部から見るとメソッドのように振舞うものです。

  クラス内部でメソッド的な書き方が出来るし、クラス外部で変数の割り当て、読み込みに使えますよ、と言い換えられます。


  サンプルでは自動実装プロパティを使いましたが、本来はこのように書きます。



static string 文字列 = "ダメな知人しかいない";
  /*プロパティとして扱うには、静的(static)な変数として宣言する これにより、
  あるメソッド内で宣言された特定のインスタンスだけでなく、クラスそのものが
  変数を保持する事になる
  http://ufcpp.net/study/csharp/oo_static.html */


private static string 文字列プロパティ
{
  get
   {
    return 文字列 ;
   }
 set {
     文字列 = value;
   }
}
 ここでのvalueとはメソッドでの引数と同じく、任意に割り当てられる値です。
それぞれgetアクセサー、setアクセサーと呼ばれます。


 getアクセサーは値の取得(読み取り)に使用します。  .
    つまり  string c = Form1.文字列プロパティ 
   のように使用します。

 setアクセサーは値を割り当てます。
  つまり  Form1.文字列プロパティ = "今日も知人がダメ過ぎる";
   という感じで値のセットに使用します。

 getアクセサーのみにして読み取り専用:Read only
     という使い方が出来ます(setアクセサーのみ:書き込み専用は推奨されていません 出来るみたいですけど意味ないですし)。


 以下、コード例です。
  実行結果 
 
 
  private void Form2_Load(object sender, EventArgs e)
        {          
            textBox1.Text = "1月13日 晴れ ";
        }


        static string 文字列 = "ダメな知人しかいない";
        private static string 文字列プロパティ
        {

            get  //Read(読み取り)
            {
                return 文字列;
    // return 文字列 + "ひつじを飼おう!"; などとコーディング出来ます;
            }

            set   //Write(書き込み)
            {
                文字列 = value;
               /* 文字列 = value.PadLeft(12);  //12文字になるまで空白を埋め込む
          コーディング例       */
            }
        }
   
    private void button1_Click(object sender, EventArgs e)
        {
    // Read(getアクセサー:読み取り)

            文字列プロパティ = textBox1.Text;
        }

        private void button2_Click(object sender, EventArgs e)
        {
    //Write(setアクセサー:書き込み)
            textBox2.Text = 文字列プロパティ + "カフェイン中毒";
        }



 ごちゃごちゃ書いてしまった気がしますが、動作は非常に単純なので、ブレイクポイントなどを設定して確認するといいと思います。
関連記事
スポンサーサイト

 挫折した人のためのC#講座

     

-   0   Comments

Leave a comment

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。