我在以下代码段中总结了我的问题。
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);
}
}
}
为什么我在标有**
的行上收到NullReferenceException异常答案 0 :(得分:5)
你实际上是在WriteLine
电话上获得了例外。(我试过了)
由于st1
已通过ref
,您传递的变量将变为null
。
ref
参数是对变量的引用,而不是对对象的引用。
因此,如果方法将其ref
参数更改为指向其他对象,则将更改其引用的变量。
答案 1 :(得分:1)
你确定你没有在下面一行NullReferenceException
(正如我所看到的那样)吗?
这是由AssignMarks(ref Student st)
正文中的引用st1设置为null引起的。
答案 2 :(得分:1)
您在下一行(Console.WriteLine(st1.Marks);
)上收到NullReferenceException,因为执行AssignMarks(ref Student st1)
后st1为空
答案 3 :(得分:1)
您应该阅读有关ValueType / Reference Type和Stack / Heap的信息。
这里,Student是一个引用类型,因此您的对象存储在Heap中。 指向此对象的指针位于Stack(因为它是一个变量)。
“方法 - 1”
当您在第一个方法(没有引用)中传递对象时,您将发送指向Heap中某个地址的指针(同样,因为Student是引用类型)。此指针被“复制”到参数,并且仅对方法是本地的。 现在,该方法可以访问该内存位置并“更改”存储在该地址中的值。
如下,
public void AssignMarks(Student st)
{
st.Marks=100;
}
在这种情况下,Program.Main方法中的WriteLine将pring 100 !!!
回到你的第一种方法。指针在方法的参数中“复制”。
通过执行'st = null'
,此本地副本指向堆中的“新”内存位置,并且原始内存位置保持原样。
因此,当呼叫返回时。你的对象保持不变。
“方法 - 2”
另一方面,当您将此参数作为“ref
”传递时,它实际上是发送指向原始变量的指针(对于ValyeType和ReferenceType,行为保持不变)。
在这种情况下,该方法可以访问变量本身的内存位置(而不是它所指向的值)。因此,如果方法更改了此参数中的任何内容,则它将在调用方法中反映为原样。
一定是吧?从各方面来说,它是从不同的地方和不同的变量访问的相同内存位置。
由于您已明确为对象指定了“null”。它抛出Null Reference异常。
希望这会有所帮助。