「あれ、変数が見つかりません」その原因、実はクラスの壁かもしれません
C#の学習が進んでコンソールアプリからWindowsフォームアプリに移ったとき、多くの人が同じところでつまずきます。
「さっきまで動いていた変数が、急に『存在しません』って怒られる…」
今日はこの現象を、コンソールアプリの小さな例から順番に見ていって、「なぜダメなのか」を理屈で納得できるようにしていきます。
まずはコンソールアプリで再現してみる
こんなコードがあったとします。
using System;
namespace StudentSample
{
internal class Program
{
static void Main(string[] args)
{
new Form1();
}
}
class Form1
{
public string helloWorld;
public Form1()
{
Console.WriteLine(helloWorld);
Student student1 = new Student();
student1.Name = "山田";
student1.ShowScore();
}
}
class Student
{
public string Name;
public int Score;
public void ShowScore()
{
Console.WriteLine(helloWorld);
}
}
}
あえてForm1という名前のクラスを使っています(この意図は後ほど回収します)。Form1クラスの中にhelloWorldという変数(正確には「フィールド」と呼びます)を用意し、コンストラクターの中でStudentを作ってShowScore()を呼び出しています。
このコードをビルドすると、Studentクラス側のhelloWorldのところにエラーが出ます。
エラー CS0103: 現在のコンテキストに 'helloWorld' という名前は存在しません
Form1のコンストラクターの中ではConsole.WriteLine(helloWorld);が問題なく通っているのに、Studentクラスの中に書いたまったく同じ一行がエラーになる。「同じnamespace StudentSampleの中に書いてあるのに、どうして見つからないの?」と思いますよね。ここが今日のポイントです。
クラスは「部屋」、フィールドは「部屋の中の私物」
変数(フィールド)を理解するときによく使う例えですが、クラスを「部屋」だと考えてみてください。
Form1クラス=Aさんの部屋Studentクラス=Bさんの部屋helloWorldという変数=Aさんの部屋に置いてある私物
Form1クラスの中に書いたhelloWorldは、あくまでForm1という部屋の中にある私物です。Studentという別の部屋にいる人が、ただ「helloWorld」と名前を呼んだだけでは、その私物を勝手に持ってくることはできません。名前を知っているかどうかと、実際に使えるかどうかは別問題なのです。
これは「同じnamespace StudentSampleの中に書いてあるから使えるはず」という感覚とはズレるところなので、最初は違和感があって当然です。namespaceはあくまで「同じ建物(アプリ)」くらいの単位で、部屋(クラス)はその中でさらに分かれている、とイメージすると整理しやすくなります。
では、どうすれば使えるのか
理由がわかったところで、直し方を考えてみましょう。ここで大事なのは、「Studentが本当に必要としているものは何か」を考えることです。
StudentのShowScore()がやりたいことは、突き詰めると「もらった文字列を表示する」だけです。Form1の部屋そのもの(ラベルもボタンも含めた全部)が欲しいわけではありません。それなら、部屋ごと渡すのではなく、必要な私物(文字列)だけを渡してあげる方がシンプルです。
呼び出す側(Form1のコンストラクター)はこうなります。
class Student
{
public string Name;
public int Score;
public void ShowScore(string message)
{
Console.WriteLine(message); // 渡された文字列を表示するだけでよい
}
}
public Form1()
{
Console.WriteLine(helloWorld);
Student student1 = new Student();
student1.Name = "山田";
student1.ShowScore(helloWorld); // 自分の部屋にある私物を、そのまま渡す
}
Form1の中ではhelloWorldは自分の部屋の私物なのでそのまま使えます。それをShowScore(helloWorld)という形で値として渡すことで、Studentは「Form1という部屋がある」ということすら知らなくても仕事ができるようになります。
これは、Form1のインスタンスごと渡すやり方(ShowScore(Form1 form))と比べると、次のような違いがあります。
| 渡し方 | Studentが知る必要があること | 特徴 |
| Form1のインスタンスを渡す | Form1というクラスの存在、その中にhelloWorldがあること | Form1の中の他のものにも触れてしまう(触りすぎる可能性がある) |
| 文字列だけを渡す | 何も知らなくてよい | 必要な情報だけを受け取るので影響範囲が小さい |



ディスカッション
コメント一覧
まだ、コメントがありません