10

初心者向けのC#に関する本を読んでいて、「値と参照を理解する」の部分にいますが、理解できないことがあります。私が見ているのは、本がこれを私に説明しようとしていることです(そして、これがYoutubeのいくつかのチュートリアルビデオでも起こっているのを見ました)、クラスがオブジェクトを作成するために使用されています....オブジェクト(? ?)クラスの。私はそれが起こった前の章全体を読みましたが、次の章でより明確になると仮定して、それを完全には理解していませんでした。はっきりしなかったので、前に説明した内容の概念を理解するまで続けるのは良い考えではないと思います。

次の部分は本の一部です:

クラスなどの参照変数を初期化するには、次のように、クラスの新しいインスタンスを作成し、参照変数を新しいオブジェクトに割り当てることができます。

Circle c = new Circle(42);
Circle copy = new Circle(99);
//Circle refc = c;
...
copy = c;

この例のコードで何ができるのでしょうか。また、なぜ便利なのですか。例と説明は大歓迎です。前もって感謝します!

4

11 に答える 11

9

それの音によって、あなたは本が説明したものを完全に理解していません:

次の目は、3と4のサイズの2つの円を作成し、最初の円のコピーを取り、それを5にします。印刷する場合を除いて、それはどのように機能したかではありません。

class Program
{
    static void Main(string[] args)
    {

        circle a = new circle(3);
        circle b = new circle(4);
        circle d = a;
        d.Diameter = 5;

        Console.WriteLine("a is {0}", a.Diameter); // shows 5
        Console.WriteLine("b is {0}", b.Diameter); // shows 4
        Console.WriteLine("d is {0}", d.Diameter); // shows 5
    }
}

class circle
{
    public int Diameter;
    public circle(int d)
    {
        Diameter = d;
    }
}

dの新しい円を作成しなかったため、実際にはdはaのエイリアスです。したがって、誰かの名前がPeterであるのと同じように、彼はPeteと呼ばれることもあります。

于 2012-07-03T14:29:20.747 に答える
5

クラスなどの参照変数を初期化するには、クラスの新しいインスタンスを作成し、その参照変数を新しいオブジェクトに割り当てることができることに注意してください。 [原文のまま]

彼は参照型と値型の違いを示しています。値型では、すでに初期化されています。

double d;

これ以上何もする必要はありません。クラスまたは参照型では、オブジェクトのインスタンスを指定する必要があります。

Circle c;まだオブジェクトが割り当てられていません。

d = c.Radius エラー。オブジェクトを指していない参照。メモリアクセス違反。

Circle c = new Circle();今ではそうです。

于 2012-07-03T14:33:54.057 に答える
4

まあ、それは便利かもしれません、そしてあなたのタイプ参照に新しいオブジェクトの場所を割り当てる可能性を常に持っている必要はありません。この場合、最後の行copy = c;で、コピーは前に割り当てられたメモリ位置を指している、cつまり、その行の後は両方とも同じメモリ位置を指していると言います。

于 2012-07-03T14:27:56.887 に答える
3

オブジェクト指向プログラミングの短期集中コースを提供するのはかなり複雑ですが、それが現時点で必要なことです。現在、多くのプログラミング言語に共通するプログラミングパラダイムであるオブジェクト指向プログラミングを理解する必要があります。もちろんC#も同様です

上記の投稿で説明している問題は次のとおりです。

oo-prgrammingでは、(大まかに)フィールドとメソッドで構成されるクラスを作成しています。これらのクラスには静的な文字があり、アプリケーションの開発時に存在します(ここで使用している静的という単語とキーワード「静的」と混同しないでください)。アプリケーションの実行時に、これらの静的*クラス*を使用してこれらのクラスのオブジェクトを作成できます。これは、特定のクラスが、すべて同一の任意の数のオブジェクトの構築計画として機能することを意味します。クラスとは対照的に、これらのオブジェクトはクラスのインスタンスとも呼ばれ、アプリケーションの実行時にのみ存在します。オブジェクトは動的

非常に短い:クラスがあるとき

class House {

// ...
}

動的な*オブジェクト*、つまり家を作成するために使用できる家の静的な記述があります。これは、いわゆるnew-operatorを使用して(C#およびJavaなどの他の現代言語で)実行しています。

House house = new House();

ここで行っているのは、House型の変数を宣言することです。クラスハウスで自分で見つけたタイプ。それはこの部分です:

House house;

これまでのところ、それは何もしないタイプHouseの変数にすぎません。ここで重要な用語は、それが何も指さないということであり、この何もnullと呼ばれます。

次に、次の構文でこのクラスのインスタンス(動的オブジェクト)を作成できます。

house = new House();

これでオブジェクトが作成され、変数houseがそのオブジェクトを指すようになりました。これ以降、変数houseを使用してこのオブジェクトを参照できます。

上記の投稿で言及した重要な問題の1つである、値型と参照型の違いを指摘するために、これをお伝えします。

前の行で行ったことは、オブジェクトを指す新しい変数を作成したことです。これは(大まかに言って)参照型と呼ばれます。それとは対照的に、たとえば、 intbyteshortなどのプリミティブ型があります。

int i = 4;

あなたは再び変数を宣言しています。ただし、今回は、変数がその値を指すのではなく、その値を直接保持します。これは値型と呼ばれます。

値型と参照型の違いは、たとえば、パラメーターなどの変数をメソッドに渡す場合に非常に重要です。

于 2012-07-03T14:46:09.397 に答える
2

それはひどいので、私はその引用を修正しようとします。

オリジナル:

クラスなどの参照変数を初期化するには、次のように、クラスの新しいインスタンスを作成し、参照変数を新しいオブジェクトに割り当てることができます。

修理済み:

参照型の変数を初期化するには、その変数の型の新しいインスタンスを作成し、次のように新しいオブジェクトを指すように変数を変更できることに注意してください。

なぜそれがあなたが覚えておくべきものであるべきなのか、私にはわかりません。はい、同じオブジェクトへの複数の参照を作成することができ、それ自体で役立つ場合がありますが、特に有用な初期化戦略としては私にはわかりません。

さらに改善されました:

参照型の変数が同じインスタンスを参照するようにすることはできますが、変数自体はエイリアスではないため、一方を上書きしても他方は変更されないことに注意してください。

于 2012-07-03T14:34:57.390 に答える
1

クラス定義は青写真です。家のように考えてください。オブジェクトをインスタンス化するたびにCircle c = new Circle(42)、その青写真で家を建設しています。各家には通りに住所があります(メモリ内の住所)。

あなたが持っているすべての変数は、家の住所をリストした一枚の紙のようなものです。したがって、123メインストリートに青い2階建ての家を建て、123メインストリートを1枚の紙に書き、その紙に「A」というラベルを付けます。次に、456 King Streetに赤い4階建ての家を建て、その住所を紙に書き留め、その紙に「B」というラベルを付けます。次に、一枚の紙を手に入れ、最初に作った家(123 Main Street)の住所を書き留め、その紙に「C」のラベルを付けます。

次に、画家のところに行き、家を黄色に塗るように頼みます。あなたは彼に紙片「C」を渡します。

この例では、家は2つしかありません。CとAは同じアドレスを「指している」ので、黄色い家を指していることになります。

House a = new House( blue, 2 );
House b = new House( red, 4 );
House c = a;
c.Color = yellow;
//Now a.Color is yellow as well
于 2012-07-03T14:40:31.773 に答える
1

クラスは、仕様や青​​写真のように、データのスキーマと考えることができます。「new」キーワードを使用すると、そのブループリントを使用してオブジェクトを作成するようにコンピューターに指示することになります。オブジェクトは、そのクラスの具体的なインスタンスです。

したがって、ブループリント(クラス定義)がある場合は、そのクラスのインスタンスを必要な数だけ生成するために、何度でもnewを呼び出すことができます。車の設計図がある場合は、その車のコピーを必要な数だけ作成できるのと同じ方法です(十分な資料があれば)。

そうすること:

Circle c = new Circle(42);
Circle copy = new Circle(99);

Circleクラス定義を使用して2つのオブジェクトをインスタンス化するようにコンピューターに指示しています(つまり、コンピューターのメモリに2つの円が存在します)。これらは、プロパティが異なるさまざまなオブジェクトです(1つは半径42、もう1つは99です)。それらは変数cとcopyに割り当てられています。

コピーを行うコードの最後の行=c; 変数cが指す円を変数コピーに入れています。

于 2012-07-03T14:35:26.807 に答える
1

変数はオブジェクトではなく、オブジェクトへの参照にすぎません。したがって、たとえば、次の例では、両方が同じオブジェクトを参照する2つの変数があります。

Label label1 = new Label();
Label label2 = label1;
label1.Text = "1";
label2.Text = "2";

そのコードを実行するとlabel1.Text、「1」ではなく「2」に等しいことがわかります。これは、両方が同じLabelオブジェクトを参照しているためです。したがって、を設定label2.Textすると、両方の変数で変更されます。ただし、2つの別々のラベルオブジェクトをインスタンス化した場合、結果は異なります。たとえば、次のようになります。

Label label1 = new Label();
Label label2 = new Label();
label1.Text = "1";
label2.Text = "2";

Labelこの2番目の例では、各変数が異なるオブジェクト(つまり、Labelクラスの異なるインスタンス)を指しています。したがって、このコードを実行した後は、予想どおり、label1.Text「1」に等しく、「2」に等しくなります。label2.Text

これらのオプションの両方が重要であり、利用できるのには十分な理由があります。たとえば、のTextプロパティを設定するメソッドを作成するとします。たとえば、次のようになりLabelます。

void SetLabelText(Label labelToSet)
{
    labelToSet.Text = "text";
}

そして、あなたはこのようなメソッドを呼び出すことができます:

Label label1 = new Label();
SetLabelText(label1);

この場合、メソッドlabelToSet内の変数は変数SetLabelTextと同じオブジェクトを参照するlabel1ため、'が"text"にSetLabelText設定されると、新しいものは作成されず、パラメーターとして渡された既存のオブジェクトにテキストが設定されるだけです。メソッド、まさにあなたが起こりたいことです。labelToSet.TextLabelLabel

どの変数も新しいオブジェクトまたは既存のオブジェクトのいずれかに設定できるため、オブジェクトに割り当てられるまでは「null」と見なされます。最初に言ったように、変数はオブジェクトではなく、オブジェクトへの参照にすぎません。変数がオブジェクトをまったく参照していない場合(初期状態)、それnullを使用しようとすると例外がスローされます。例えば:

Label label1; 
label1.Text = "1";  // Throws a null reference exception

必要な数の変数を宣言できますが、null実際に少なくとも1つのオブジェクトをインスタンス化してそれに設定するまで、すべての変数が宣言されます。オブジェクトをインスタンス化するには(つまり、クラスの新しいインスタンスを作成するには)、newキーワード(eg new Label())を使用する必要があります。

ただし、これまでに述べたことはすべて、「参照型」(クラス)にのみ当てはまります。これは「値型」(構造体)には当てはまりません。変数を値型として宣言する場合、すべての実用的な目的で、それは実際にはオブジェクトです。のような多くの単純なデータ型intは値型です。たとえば、次のようになります。

int x;
int y;
x = 1;
y = x;
y = 2;

上記のコードを実行した後、xは等しく1なり、y等しくなります2。設定しても、と同じオブジェクトを参照するy = xことはありません。むしろ、からに値をコピーし、それによって新しい値型オブジェクトを作成します。yxxy

于 2012-07-03T14:42:34.270 に答える
0

このコンテキストで人間を参照する場合、クラスは人間とは何か、何ができるかを定義し(height、widthなどのメンバーであり、メソッドeat()、drink()など)、オブジェクトは実際の人間を表します(幅が食べたり飲んだりできる高さのアンドリューという人)

于 2012-07-03T14:33:22.200 に答える
0

間違っている場合は訂正してください。ただし、コードを見ると、2つのオブジェクトが作成されており、値を指しているのはそれぞれのメモリ位置です。

コピー=c; 行は、コピーオブジェクトが、最初に設定されたものではなく、cオブジェクトのメモリ位置をポイントしないことを示しています。

于 2012-07-03T14:34:52.180 に答える
0

あなたが提供した例では、そして本によって提供された多くの例の場合と同様に、あなたは最も基本的なケースを見ています。実際にコードを深く理解するまで、このような機能を使用するための最良の方法を理解するのは困難です。

これが正確に正しいかどうかはわかりませんが、次のようなものを使用する方法は次のとおりです。

private double GetArea(Circle c)
{
     //this will be a default circle should the passed in circle be invalid
     Circle toCalc = new Circle(5);

     //check to make sure c is valid
     if(c != null)
          toCalc = c;

     return Math.pow(toCalc.Radius, 2) * Math.Pi;
}

toCalcはクラスであり、プリミティブデータ型ではないため、コードをコンパイルするには初期化する必要があります。初期化されていない場合、コンパイラは「toCalcが初期化されていない可能性があります」などのエラーを表示します。

于 2012-07-03T14:36:23.553 に答える