0

私はこのようなプログラムを持っています

    class Program
    {
        static void Main(string[] args)
        {
            test objtest = new test();
            objtest.Name = "vikas";
            Test(objtest);
            //objtest = null; when I uncomment this line it shows me exception
            Console.WriteLine(objtest.Name);
            Console.ReadLine();
        }

        private static void Test(test objtest)
        {
            objtest.Name = "chetan";
            objtest = null;
        }
    }

    class test
    {
        private string _Name = string.Empty;
        public string Name
        {
            get
            {
                return _Name;
            }
            set
            {
                _Name = value;
            }
        }
    }

出力: chetan

2 番目のプログラム:

    class Program
    {
        static void Main(string[] args)
        {
            test objtest = new test();
            objtest.Name = "vikas";
            Test(objtest);
            objtest = null;
            try
            {
                Console.WriteLine(objtest.Name);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.InnerException + " " + ex.Message);
            }

            Console.ReadLine();
        }

        private static void Test(test objtest)
        {
            objtest.Name = "chetan";
            objtest = null;
        }
    }

    class test
    {
        private string _Name = string.Empty;
        public string Name
        {
            get
            {
                return _Name;
            }
            set
            {
                _Name = value;
            }
        }
    }

出力:

オブジェクトのインスタンスを設定しないオブジェクト参照

なんで?テストで設定objtest = null;すると値が表示されますが、同じように null を設定するとエラーが表示されます。

@kmatyaszek の投稿の後に追加:

最初のプログラムで

static void Main(string[] args)
        {
            test objtest = new test();
            objtest.Name = "vikas"; // **I am assigning this value**
            Test(objtest);
            //objtest = null; when I uncomment this line it shows me exception
            Console.WriteLine(objtest.Name);
            Console.ReadLine();
        }

        private static void Test(test objtest)
        {
            objtest.Name = "chetan";
            objtest = null;
        }

「vikas」ではなく「chetan」と表示されるのはなぜですか??

4

3 に答える 3

1

値渡しされる参照型によって引き起こされる古典的な混乱。

ここでは、かなり短く簡単な答えを出します。さらに深く学びたい方は、C# でのパラメーターの受け渡しに関するJon Skeet の記事と、Lee Richardson による同様の記事(ダイアグラム付き) をお読みください。

つまり、参照型は、プリミティブでも構造体でもない任意の型です。したがって、任意のカスタム定義クラスは参照型です。

そのようなクラスのインスタンスが関数に渡されると、実際には、このインスタンスへのポインターが渡されます。より正確には、デフォルトではパラメーターは値で渡されるため、ポインターのコピーが渡されます。

この行がある場合:

test objtest = new test();

クラスの新しいインスタンスtestが作成され、メモリ内のアドレスが割り当てられています。変数を参照するたびにobjtest、そのアドレスが次のように使用されます。

objtest.Name = "vikas";

ランタイム エンジンは、インスタンスの作成時に割り当てられたアドレスに移動し、プロパティName用に予約された場所を探し、その内容を「vikas」に変更します。このインスタンスの変更は即時かつ永続的です。

そのような関数シグネチャがある場合:

private static void Test(test objtest)

「舞台裏」で渡される実際のパラメータは、メモリ内のインスタンスのアドレスです。関数内でパラメーターを参照するとobjtest、ランタイム エンジンは、実際のパラメーターとして渡されたアドレスに移動します。したがって、関数内に次の行があります。

objtest.Name = "chetan";

関数の外に置くのとまったく同じです: 渡されたメモリアドレスでプロパティName用に予約された場所を探し、その内容を「chetan」に変更します。繰り返しになりますが、この変更はそのインスタンスに対して即時かつ永続的です。このこと(プロパティの変更)についてはref、参照型を扱っているため、使用しているかどうかは関係ありません。

ただし、値で (たとえば、refキーワードなしで) 渡されるということは、メモリ アドレスがコピーされ、関数は整数を渡すのと同じようにコピーを取得するだけであることを意味します。コピーを変更しても、元の値には影響しません。したがって、関数内に次の行がある場合:

objtest = null;

コピーを変更して何も指定しないようにしますが、関数の外側の変数は引き続き同じアドレスを指し、null にはなりません。

そのような関数シグネチャがある場合:

private static void Test(ref test objtest)

次に、アドレス自体が参照によって渡されることを意味するため、アドレスを保持する変数を変更すると、関数の外部でも変更されます。

これはかなり要約しています。ここでは、より単純な説明と思われるもので物事を明確にするだけで、新しいことは何も持ち出しません。

于 2013-01-21T15:45:54.350 に答える
0

という値を持つオブジェクトを使用しているnullため、例外が発生します。null参照型の場合、「ゼロを指す」ことを意味します。アドレス 0 に格納されている値にアクセスしようとすると、NullReferenceException.

プロパティにアクセスする前に に設定objtestしているため、アドレス 0 に格納されているオブジェクトのプロパティにアクセスしようとしていますが、これは意味がありません。nullNameName

于 2013-01-20T11:19:29.373 に答える
0

You have problem here with passing parameter to function.

Default parameters are passed by value.

The attempt to reassign the parameter to a different memory location only works inside the method Test and does not affect the original variable objtest in Main method.

So when you add ref to parameter in Test function in two cases behaviour will be the same, because all of the changes that take place inside the method Test affect the original object objtest in Main method.

First example from your question with ref parameter:

 class Program
    {
        static void Main(string[] args)
        {
            test objtest = new test();
            objtest.Name = "vikas";
            Test(ref objtest);
            //objtest = null; when I uncomment this line it shows me exception
            Console.WriteLine(objtest.Name);
            Console.ReadLine();
        }

        private static void Test(ref test objtest)
        {
            objtest.Name = "chetan";
            objtest = null;
        }
    }

    class test
    {
        private string _Name = string.Empty;
        public string Name
        {
            get
            {
                return _Name;
            }
            set
            {
                _Name = value;
            }
        }
    }

In the second example first you set null to original object and after that you want read property Name, so you will get NullReferenceException.

于 2013-01-20T10:40:53.630 に答える