ここから本文です

(C#)静的でないフィールド、メソッド、またはプロパティ で、オブジェクト参照...

アバター

ID非公開さん

2010/3/3104:21:22

(C#)静的でないフィールド、メソッド、またはプロパティ で、オブジェクト参照が必要です

public bool i ;

void test(bool a)
{
a = false;

}



static void Main(string[] args)
{
test(i);



}

というプログラムを書くとtest(i)に対して「静的でないフィールド、メソッド、またはプロパティ で、オブジェクト参照が必要です」
というエラーが出ますがその理由がわからないので教えて下さい。

この質問は、活躍中のチエリアン・専門家に回答をリクエストしました。

閲覧数:
81,718
回答数:
2
お礼:
50枚

違反報告

ベストアンサーに選ばれた回答

ttk********さん

2010/3/3110:37:21

静的メンバ内のコードからインスタンスメンバにアクセスできないという言語仕様上の決まりごとです。

生成されている、されていないの問題ではありません。また、Main メソッドであることは間接的な原因で、直接的な原因は上記に書いた言語仕様上の決まりごとです。

static が付いていないメンバは各インスタンス固有のメンバになります。一方、static が付いているメンバはすべてのインスタンスで共有される共有メンバとなります。

例えば

public class Test
{
public int A;
public void B()
{
Console.WriteLine(A.ToString())
}
public static void C()
{
Console.WriteLine(A.ToString())
}
}

とすると、メソッドCの中で、質問者さんと同じコンパイルエラーとなります。

インスタンスというのは複数存在できますから、例えば(コンパイルエラーがなかったと仮定すると)

Test t1 = new Test1();
t1.A = 100;

Test t2 = new Test2();
t2.A = 200;

とすれば、

t1.B();

なら 100 が出力されますし、

t2.B();

なら200 が出力されます。インスタンスごとに A の値を保持しているのがわかりますね。

しかし、C は共有メンバですので、インスタンスを作らずに、クラス名.メソッド名で呼び出します。

Test.C();

こう書かれたときに、先のコードでは、どのインスタンスの A を出力すればよいのかが不明確になってしまいます。

こういったことから、static なメソッドのコードからは、static でない自クラスのメンバにはアクセスできないという決まりがあるのです。static の意味(共有)を考えれば当然でもあるわけですが。


質問者さんのコードに戻りますが、エントリポイントとなる Main メソッドは static でなくてはならないという決まりがあるので、static になっています。ですから、その Main からフィールド i やメソッド test を使いたいのであれば、それらも static にする必要があります。

アバター

質問した人からのコメント

2010/3/31 23:39:31

例が勉強になったのでこちらの回答にさせてもらいました。
ベストアンサーに両方出来ればしたかったです。
回答ありがとうございました。

ベストアンサー以外の回答

1〜1件/1件中

abi********さん

編集あり2010/3/3117:18:49

[理由]


理由は、Main()メソッドは、「スタートアップ(一番最初に実行されるプログラム)」の役割りを担っているからです。

もう少し正確に言いますと、Main()メソッドをメンバーに持つProgramクラスは、スタートアップクラスだからです。
そのため、Programクラスのメンバー(メンバーメソッド、メンバー変数等)は、静的メンバーとするように、staticを指定する必要があります。



[staticの指定方法]

Main()の周囲のメソッド等は、静的メンバーにする必要がありますので、質問のメソッドtest()は、以下のようにstaticを指定します。
例えば、


public static void test(bool a)
{
a = false;
}





[静的メンバーの特徴]

静的メンバーは、クラスのオブジェクトを生成しなくても、そのメンバーを使うことが可能だという特徴があります。
例えば、MyClassという名のクラスのメンバーに、MyFunc()と言う静的メソッドを持つとします。

static class MyClass
{

public static void MyFunc(bool a)
{
a = false;
}

}

そのメソッドMyFunc()を利用する場合、普通のやり方ならば、クラスのオブジェクトを生成するでしょう。
例えば、

MyClass obj;
obj.MyFunc(true);

しかし、おそらく上記はエラーとなります。
静的メソッドの使い方は、オブジェクトは生成しないで、直接そのメソッドを呼び出します。以下のように。

MyClass.MyFunc(true);

この使い方は、見覚えがあると思います。
システム側が(マイクロソフトが)用意しているメソッドでは、このような使い方をするものがあります。
例えば、メッセージボックスを表示するメソッドです。

MessageBox.Show("こんにちは");

というように。



なぜ、このような説明をしたのかと言いますと、変数やメソッド等に静的(static)を指定すると言う事は、その変数、又はメソッドに対して、
「メモリから解放されることなく、いつまでも居座っていなさい」
と指示しているからです。
いつまでもメモリに存在するので、オブジェクトを生成しなくても利用することが可能なわけです。


さて、前述の通り、Main()メソッドは、実行開始のエントリーポイントになります。これは、多くの言語で共通的な常識です。
これは、プログラマーが自分で作るプログラムの中では、Main()メソッドはシステム側のような立場という事です。
よって、システム側のMessageBox.Show()のように、いつまでもメモリ上に存在する必要があります。





[WindowsフォームアプリでのMain()]


まだ、ぴんと来ない場合のために、以下の説明で補足します。



さて、コンソールアプリケーションを専門に作られているプログラマーにとっては、「なぜ、やたらに static を指定する必要があるのだろう?」と疑問に思う人もいると思います。

しかし、Windowsフォームアプリケーションでは、基本的に static の指定をすることは、あまりありません。
これは、Windowsフォームアプリでは、Main()メソッドを使う機会が無いからです。
しかし、Main()メソッドが無い訳では無く、実際には存在します。
Program.csファイルを開くと、Programクラスと、そのメンバーのMain()が存在しています。

すなわち、Main()の関連(Programクラス全体)が、がっちりとメモリに居座っていて、そこからフォーム関連のプログラムが呼び出されて実行されています。


試しに、Main()内の

Application.Run(new Form1());

と書かれたコードの下に

MessageBox.Show("アプリが終了されました。");

と記述して下さい。
そして、ビルドと実行を行ってみて下さい。
そうすると、アプリを終了すると、「アプリが終了されました。」と言うメッセージボックスが起動されます。
これはアプリ終了後には、Main()への処理へ戻っている事を意味します。
すなわち、Main()が中心となる基盤になっている事を意味します。
よって、静的である必要があります。
Main()側のソースと、フォーム側のソースが分離されている構造なので、フォーム側の処理からMain()側に戻る際に、コンパイラーがMain()を見つけることが可能なように、Main()側はstatic にしてあります。




[まとめ]

まとめますと、コンパイラーがMain()を見つけることが可能なように、Main()側( Main()と、Main()を含むProgramクラス内 )はstatic にしています。
このような、構造上の原理的な理由によります。





[余談]


Windowsフォームアプリで、Programクラスの並びに、自分で定義した静的クラスを作ってみて下さい。
例えば、前述のMyClassクラスで、MyFunc()の処理は、メッセージボックス表示にするなどの処理にして。
それをフォーム側のソースで呼び出して見て下さい。


また、プロジェクトの種類がコンソールアプリの場合でも、フォームクラスを定義すれば、Windowsフォームアプリが作れます。
(コンソール用の窓が起動してしまう事が欠点ですが)


その手の事をやってみると、構造上の原理が理解しやすいと思います。

あわせて知りたい

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる