为什么在构造函数中抛出异常导致空引用?

Set*_*o N 21 c# null constructor exception object

为什么在构造函数中抛出异常导致空引用?例如,如果我们运行下面的代码,则teacher的值为null,而st.teacher则不是(创建了Teacher对象).为什么?

using System;

namespace ConsoleApplication1
{
  class Program
  {
    static void Main( string[] args )
    {
      Test();
    }

    private static void Test()
    {
      Teacher teacher = null;
      Student st = new Student();
      try
      {
        teacher = new Teacher( "", st );
      }
      catch ( Exception e )
      {
        Console.WriteLine( e.Message );
      }
      Console.WriteLine( ( teacher == null ) );  // output True
      Console.WriteLine( ( st.teacher == null ) );  // output False
    }
  }

  class Teacher
  {
    public string name;
    public Teacher( string name, Student student )
    {
      student.teacher = this;
      if ( name.Length < 5 )
        throw new ArgumentException( "Name must be at least 5 characters long." );
    }
  }

  class Student
  {
    public Teacher teacher;
  }

}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 39

构造函数永远不会完成,因此永远不会发生赋值.它不是从构造函数返回null(或者有一个"null对象" - 没有这样的概念).只是你永远不会分配新的值teacher,所以它保留了以前的值.

例如,如果您使用:

Teacher teacher = new Teacher("This is valid", new Student());
Student st = new Student();
try
{
    teacher = new Teacher("", st);
}
catch (... etc ...)
Run Code Online (Sandbox Code Playgroud)

...那么你仍然会有"这是有效的"老师.但是,name变量仍然不会在该Teacher对象中赋值,因为您的Teacher构造函数缺少一行,例如:

this.name = name;
Run Code Online (Sandbox Code Playgroud)

  • @ Hi-Angel:不,这不是一个bug.这是*field*和局部变量之间的区别.一个字段有一个默认值,可以在没有设置的情况下使用 - 局部变量*在被明确分配之前不能被读取. (4认同)

Tig*_*ran 13

因为你正在检查参考.

  try
  {
    teacher = new Teacher( "", st ); //this line raises an exception 
                                     // so teacher REMAINS NULL. 
                                     // it's NOT ASSIGNED to NULL, 
                                     // but just NOT initialized. That is.
  }
  catch ( Exception e )
  {
    Console.WriteLine( e.Message );
  }
Run Code Online (Sandbox Code Playgroud)

public Teacher( string name, Student student )
{
  student.teacher = this;  //st.Teacher is assigned BEFORE exception raised.
  if ( name.Length < 5 )
    throw new ArgumentException( "Name must be at least 5 characters long." );
}
Run Code Online (Sandbox Code Playgroud)