2010-12-08 105 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”明确指定给您的对象。它抛出空引用异常。

希望这会有所帮助。