C#の変数スコープについて

このQ&Aのポイント
  • C#のNet 2.0で同一名の変数を使う場合、変数スコープによって挙動が異なる。
  • Hoge1ではローカルの変数 'x' を宣言することができず、'親またはカレント' スコープの変数としての 'x' の意味が変更される。
  • 一方、Hoge2では再宣言することでローカル変数としての 'x' を宣言でき、'親またはカレント' スコープの変数には影響を与えない。
回答を見る
  • ベストアンサー

C#での変数スコープ?

Net 2.0のC#で同一名の変数を使う場合について質問いたします。 以下のHoge1の場合には「 ローカルの変数 'x' をこのスコープで宣言することはできません。これは、'親またはカレント' スコープで別の意味を持つ 'x' の意味が変更されるのを避けるためです。」と怒られます。 一方、Hoge2の場合には怒られません。 Hoge2内でx=1;ではなくint x=1;と再宣言しているにもかかわらず怒られないのは、Hoge1が厳格にスコープ管理している点からみると意外に感じられます。 http://www.atmarkit.co.jp/ait/articles/0210/16/news001_5.html の記述を見ると、この記事が書かれた2002年ごろにはHoge2もNGだったような印象を受けるのですが、変化があったのでしょうか? この辺りの事情に詳しい方がおられましたらよろしく、お願い申し上げます。 class Class1 {    private void Hoge1()    {       int x;       {          int x = 2; // これはNG!。「ローカルの変数 'x' をこのスコープで宣言することはできません。これは、'親またはカレント' スコープで別の意味を持つ 'x' の意味が変更されるのを避けるためです。」と怒られる。       }    }    int x;    private static void Hoge2()    {       int x=1; //これはOK!親にぶらさげた変数が通る。    } }

質問者が選んだベストアンサー

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8518/19364)
回答No.2

>変化があったのでしょうか? 質問文で掲示されているページの記事と、質問者さんの例(ほげ1ほげ2)は、表記は違えど「同じ事を言っている」ように見えるんですが。 「何も変わってない」と思いますが、どうでしょう?

creamysoft
質問者

お礼

ご回答ありがとうございます。 //http://www.atmarkit.co.jp/ait/articles/0210/16/news001_5.html からのコピペ改変(xをyに変更) private static int y = 0; static void sample1() {     int y = 2; // ローカルの変数 'x' をこのスコープで宣言することはできません。これは、'親またはカレント' スコープで別の意味を持つ 'x' の意味が変更されるのを避けるためです。 } 上記を、VisualStudio2012でコピペで動かしてもやはりエラーが発生しないのであります...... ------------------------------------------------------------------ その後、自分でも検討した結果、以下のことが分かったので後学のために記述します。 public class Class1 {     private void Hoge1()     {         int x;         {             int x = 2; // これはNG!。「ローカルの変数 'x' をこのスコープで宣言することはできません。これは、'親またはカレント' スコープで別の意味を持つ 'x' の意味が変更されるのを避けるためです。」といわれる。         }     }     int x;     private void Hoge2()     {         int x = 1; //このぶらさげ変数はOK!     } (1)Hoge2の{ }内のint x = 1;のxは{ }内のみにスコープを持つローカル変数として宣言されており、親のint x;とは無関係でスコープは及んでいない。→これは理解できる仕様である。 (2)ところが、Hoge2の{ }内のint x = 1;実行直後、親のint xにマウスをホーバーさせて内容をクイックウォッチすると1がはいってる(ように見えるため)、スコープが親のint xに通ってる(ように見える)!!→「え’’~、おかっしいなぁ」と感じる。 (3)これは、クイックウォッチが変数名のみで判断して中身表示してるためのようで、イミディエイトウインドウでClass1.xをみるとnullのままである。したがって、Hoge2の{ }内のローカル変数xのスコープは、親のxに及んでいないことがわかる。 ------------------------------------------------------------------ 上記より、 a)クイックウォッチの仕様にやや問題があるのでは? b)昔の文法のほうが厳格で、親にぶら下げたglobal的変数名をローカルで宣言してまったときに気づきやすい。よって、今の文法でも「ローカルの変数 'x' をこのスコープで宣言することはできるが、'親またはカレント' スコープでも同一名で宣言されてるが、わかってるんだろうな!」くらいの警告がほしい。

その他の回答 (1)

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

詳しいって訳ではありませんが……。 # ということで、正しい内容についてはもっと詳しい方の回答待ちになりますかな。 >int x = 2; // これはNG!。 エラーで書かれているように、Hoge1()直下でのローカル変数なのか、その下に作ったローカルなブロック内での変数なのか判別する手段がない(あるいは煩雑過ぎる)ので駄目なのでしょう。 >int x=1; //これはOK!親にぶらさげた変数が通る。 静的メソッドから、非静的クラスフィールド(int x;)へのアクセスはできませんから判別できない。という状況にはならないのでしょう。

参考URL:
http://ufcpp.net/study/csharp/oo_static.html
creamysoft
質問者

お礼

ご回答ありがとうございます。     int x;     private void Hoge2()     {         int x = 1; //このぶらさげ変数はOK!     } とstaticをはずしても、相変わらず//ぶらさげ変数はOK!となる模様であります。。

関連するQ&A

  • C++ 静的クラスの役割が分からない

    こんばんは。 C++で静的オブジェクトがなんなのか試しにプログラミングしているんですが どんな役割があるのか試してもよく分かりません。 static class HOGE { public: int *hoge; private: int value[2]; char moji[6]; public: HOGE() { cout << "HOGE\n"; } void MOJI() { strcpy(moji, "MOJI\n"); } void TEST() { cout << "moji = " << moji << endl; } static void staticMOJI() { } }sObj; sObjからは静的メンバ関数と静的メンバ変数は呼び出せるようです。他は呼び出せません。 そのようにするためにstatic宣言をするものなのでしょうか? このsObjからメンバ変数(*hoge)を呼び出すことは無理なんでしょうか?

  • return の中はローカルスコープ?

    return 範囲内における、ローカル / グローバルスコープについて教えてください ■質問 ・returnするまではローカル変数? ・returnしたらグローバル変数? ・それとも、「return の中」というスコープは存在しない? ■例1 (function(){  return{   //ローカルスコープ?   //ここで定義した変数はローカル変数?  } })(); ■例2 (function(){  return{   hoge : (function(){    //ローカルスコープ?    //ここで定義した変数はローカル変数?   })()   }; })();

  • staticのスコープについて

    //main.c #include "myfunc.h" #include <stdio.h> static char hoge[10]; int main(void){ myfunc(hoge); printf("%c",*hoge); } ------------------ //myfunc.h void myfunc(char *hoge) { *hoge = 'a'; } 上記のようなプログラムの場合、 a と表示されると思いますが、この動作は保証されているのでしょうか? つまり、staticにて宣言したモジュール内の変数は、他モジュールにポインタを渡しても、内容は保証されるのかどうかと言う事なのですが。 よろしければ教えてください。

  • フレンド宣言のスコープがわかりません。

    フレンド宣言のスコープがわかりません。 #include <iostream> class X { friend class Y; friend void f() { std::cout << "f()" << std::endl; } }; //class Y; //void f(); class Z { Y *ymem; void g() { ::f(); } }; int main() { ::f(); return 0; } C++プライマー第4版を読んでいます。511ページに上記のプログラムがあり、 「フレンドで導入されたクラスと関数(定義または宣言)は、すでに宣言されたものとして使うことができる。」 と説明されています。 しかし、g++(gcc4.4.1)でコンパイルするとエラーになります。コメント部分を外すと実行できます。 C++プライマーが正しいのか、gccが正しいのか、私が思い違いをしているのか、わかりません。 ご存知の方はいませんか。

  • javaのローカル変数について

    基本的なことの質問ですがよろしくお願いいたします。 下記の様なソースコードでint y ;はローカル変数にあたると思いますが 確かローカル変数は初期化されないとコンパイルエラーになるはずなのですが どうもコンパイルも実行もできます。 どうしてでしょうか? よろしくお願いいたします。 class Test1{ static int x = 0; } public class Test extends Test1{ public static void main(String args[]){ Test i = new Test(); int y ; y = ++x; System.out.println( y ) ; } }

    • ベストアンサー
    • Java
  • 変数の隠蔽とスコープ

    いつまでも初心者のままじゃ駄目だなあと思い, 用事のついでに本屋まで行って 評価が高いらしい http://www.amazon.co.jp/exec/obidos/ASIN/4797328541/Lvdrfree-22?dev-t=D1KDF7Q74DD3A2%26camp=2025%26link_code=xm2 を100ページほど立ち読みしてみた。(買ってません) で、まあ内容を理解できているかは別として 可視性とアクセス制御という話があって Java や C#の時の知識から 以下のコードの出力結果は一応理解できます。 折角なので 質問もコードの中に書いてみました。 ========================== #include <iostream> int a = 5; class fuga{ public: int a; fuga(){ a = 3; } }; class hoge : fuga{ //実際の書籍では public fugaだったような public: void printa(){ std::cout << a << std::endl; //コンパイル通っちゃったけど,ここからグローバル変数a(==5)にアクセスする方法はあるの? } }; int main(){ hoge* p = new hoge; p->printa(); std::cout << a << std::endl; delete p; // 3 // 5 }

  • 『sun教科書 javaプログラマ』で勉強している者です

    javaの資格を取るべく独学中の者なのですが、回答を読んでも何故そうなるのか理解できない問題に出くわして困っています。ご教授いただければ助かりますm(__)m [問題3-15] 次のコードがあります。 public class CodeWalkTwo { int x = 3; static int y = 2; public static void main(String[] args){ int x = 10; int y = 10; CodeWalkTwo boardWalk = new CodeWalkTwo(); boardWalk.printIt(); boardWalk.printIt(y); } {x = x+1;} static{y += y;} void printIt(){ System.out.print(++x); } void printIt(int y){ System.out.print(" " + ++y); } } 実行結果は次のどれですか。 A. 5 11 B. 11 11 C. 5 5 D. 17行目でコンパイルエラーが発生する E. 5行目と6行目でコンパイルエラーが発生する 正解はA。その理由は2・3行目で宣言されるインスタンス変数およびstatic変数と、5・6行目で宣言されるローカル変数とは異なるスコープだからなのだそうですが、解説が短すぎてよく分かりません>< なぜ、片方はインスタンス変数でもう一方はローカル変数を実行しているのでしょう?

    • ベストアンサー
    • Java
  • Cの変数の初期化のタイミングについて

    以下のようなCの演習プログラムについてお尋ねします。 やっていることは、inc_counterと言う関数を呼び出して呼び出すたびに変数を1つづつ増やすというもので、10回呼び出すので変数が10になるというものです。この演習プログラムが言いたいことは変数counterの動作ということです。 externですべての関数の外側で宣言されているから呼び出す側、呼び出される側で共通になっているということですが、void inc_couter(void)の実体(後方)の前にint counter=0;となっています。この文は変数counterの初期化ということだと思いますが、これが実行されるのはいつなのでしょうか。関数inc_counerの呼び出しのときは実行されないのでしょうか。もしそうなら関数が呼び出されるたびに初期化されるはずですが、そうではないのでしょうか。 変数のスコープとか初期化とかの問題だと思いますが、この辺を間違って理解すると大けがをしそうなのでお尋ねします。よろしくお願いします。 #include<stdio.h> extern int counter; void inc_counter(void); main() { int index; for(index=0; index<10; index++) inc_counter(); (void) printf("Counter is %d\n",counter); return (0); } int counter=0; void inc_counter(void) { counter++; }

  • [C#]Public変数の使い方

    今までVBを使っており、C#は初心者です。 VBでは、各関数にまたがって使う変数は、 private Hensu as integer Sub Kansuu1() Hensu = 2 Call Kansuu2() End Sub Sub Kansuu2() MsgBox Hensu End Sub と宣言すれば、使えますが、C#でそのような使い方はできないのでしょうか? 変数Hensu3をMainとMain2双方で使いたいとき、 using System; namespace ns1 { static class Program { public string Hensu3; static void Main(string[] args) { ・・・ } static void Main2() { ・・・ } } } と書きましたが、ビルドエラーになります。

  • 関数スコープの変更の仕方について

    こんにちは。いつも勉強させていただいております。 VB2005始めて間もない初心者なので分かりにくい表現が多々あるかと思いますが よろしくお願いいたします。 現在2つのプロジェクトを作っていて、どちらもxxx.dllというファイルを参照しています。 やりたいことは、xxx.dll内でグローバル変数として宣言しているyyy変数の関数スコープを動的に変更したいと思っております。 プロジェクト1ではyyy変数の関数スコープをPrivate プロジェクト2ではyyy変数の関数スコープをPublic なお、このxxx.dllは他にも色々と使われており、基本はPrivateのままにしておきたいので、 最初からxxx.dllのグローバル変数のスコープをPublicにすれば良いということはできません。 特定のプロジェクトから呼び出されたときだけPublicにすることは可能でしょうか? どうぞよろしくお願いいたします。

専門家に質問してみよう