2010-12-08 112 views
1

我在下面的代碼片段中總結了我的問題。值類型和參考類型

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication13 
{ 
    public class Student 
    { 
     public int Marks { get; set; } 
     public Student(int marks) 
     { 
      this.Marks = marks; 

     } 
     public void AssignMarks(Student st) 
     { 
      st = null; 
     } 
     public void AssignMarks(ref Student st) 
     { 
      st = null; 
     } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Student st = new Student(50); 
      st.AssignMarks(st); 
      Console.WriteLine(st.Marks); 
      Student st1 = new Student(50); 
      st.AssignMarks(ref st1); // NullReferenceException 
      Console.WriteLine(st1.Marks); 
     } 
    } 
} 

爲什麼我上標有**

+0

好吧,異常的類型可能有所幫助 – BlackICE 2010-12-08 15:35:48

+0

我編輯了我的問題。我得到NullReferenceException – 2010-12-08 15:38:15

回答

5

你實際上得到的WriteLine電話除外。(我試過)

因爲st1傳遞ref,您傳遞變得null變量。

A ref參數是對變量的引用,而不是對對象的引用。
因此,如果方法將其ref參數更改爲指向不同的對象,則其參考被傳遞的變量將被更改。

1

你確定你不是在下面的橫線得到一個NullReferenceException(因爲我看到)行越來越NullReferenceException異常?

這由基準ST1造成被設置爲空在AssignMarks(ref Student st)體內。

1

你在下一行(Console.WriteLine(st1.Marks);),因爲ST1是執行AssignMarks(ref Student st1)

1

你應該閱讀有關值類型/引用類型和堆棧/堆後空得到的NullReferenceException。

在這裏,學生是引用類型,所以你的對象存儲在堆。 指向這個對象的指針位於Stack中(因爲它是一個變量)。

「方法 - 1」

當通過在第一方法(沒有REF)的對象,要發送一個指向在堆一些地址指針(再次,由於學生是引用類型)。該指針被「複製」到參數中,並且僅在方法的本地。 現在該方法可以訪問該內存位置並「更改」存儲在該地址中的值。

如下,

public void AssignMarks(Student st) 
     { 
      st.Marks=100; 
     } 

在這種情況下,在的WriteLine方法Program.Main將普林100 !!!

回到你的第一個方法。指針在您的方法的參數中「複製」。 通過這樣做,'st = null',此本地副本指向堆中的「新」內存位置,並且原始內存位置保持原樣。 因此,當通話返回時。你的對象保持不變。

「方法 - 2」

在另一方面,當你通過這個參數爲「ref」,它實際上是發送指向你的原始變量(行爲保持相同的ValyeType和引用類型)。 在這種情況下,該方法可以訪問變量本身的內存位置(而不是它指向的值)。所以,如果該方法改變了這個參數中的任何內容,它就會在調用方法中反映出來。 必須是,對吧?在任何意義上,它都是從不同地點和不同變量訪問的相同內存位置。

由於您已將「null」明確指定給您的對象。它拋出空引用異常。

希望這會有所幫助。