属性或字段为 null
当创建某个类时,该类的字段和属性将自动初始化为其默认值。 引用类的默认值为 null(在 Visual Basic 中为 Nothing),在字段或属性值为 null 时调用父类的字段或属性的成员方法会导致 NullReferenceException。
在此示例中,突出显示的代码行将引发 NullReferenceException,因为 car 的 Engine 属性将自动初始化为 null。
public void NullReferenceFromProperty()
{
var car = new Automobile();
Console.WriteLine(car.Engine.ToString());
}
方法的返回值为 null
返回引用类型的方法可返回 null(在 Visual Basic 中为 Nothing)。 在引用为 null 时,调用返回的引用类型的方法或属性会导致 NullReferenceException。
在本示例中,突出显示的行将引发 NullReferenceException,因为对 BadGetEngineInfo 的调用在 NullReferenceFromMethodParameter 方法中返回 null 引用。
public EngineInfo BadGetEngineInfo()
{
EngineInfo engine = null;
return engine;
}
public void NullReferenceFromMethodReturnValue()
{
var engine = BadGetEngineInfo();
Console.WriteLine(engine.ToString());
}
集合或数组中的某个对象为 null
引用类型的列表或数组可能包含值为 null 的项。 为 null 的列表项的调用方法或属性会导致 NullReferenceException。
在此示例中,NullReferenceFromListItem() 中突出显示的代码行将引发 NullReferenceException,因为对 BadGetCarList 的调用将返回一个值为 null 的项。
public Automobile[] BadGetCarList()
{
var autos = new Automobile[10];
for (int i = 0; i autos.Length; i++)
{
if (i != 6)
{
autos[i] = new Automobile();
}
}
return autos;
}
public void NullReferenceFromListItem()
{
var cars = BadGetCarList();
foreach (Automobile car in cars)
{
Console.WriteLine(car.ToString());
}
}
由于存在某个条件,所以不创建对象
若在条件块中初始化引用类型,则在该条件为 false 时,将不会创建对象。
在本示例中,NullReferenceFromConditionalCreation 中突出显示的行将引发 NullReferenceException,因为它仅当 DetermineTheCondition() 方法返回 true 时才初始化 engine 变量。
public bool DetermineTheCondition()
{
return false;
}
public void NullReferenceFromConditionalCreation()
{
EngineInfo engine = null;
var condition = DetermineTheCondition();
if (condition)
{
engine = new EngineInfo();
engine.Power = "Diesel";
engine.Size = 2.4;
}
Console.WriteLine(engine.Size);
}
传递给方法的对象属性设置为 null
当对象作为参数按值传递给方法时(不在 C# 中使用 ref 或 out 关键字或在 Visual Basic 中使用 ByRef),该方法无法更改参数的内存位置(参数所指向的位置),但可以更改对象的属性。
在本示例中,NullPropertyReferenceFromPassToMethod 方法创建 Automobile 对象并初始化 Engine 属性。 然后它将调用 BadSwapCarEngine,将新对象作为参数传递。 BadSwapCarEngine 将 Engine 属性设置为 null,这会导致 NullPropertyReferenceFromPassToMethod 中突出显示的代码行引发 NullReferenceException。
public void BadSwapCarEngine(Automobile car)
{
car.Engine = null;
}
public void (Automobile car)
{
car.Engine = new EngineInfo("GAS", 1.5);
BadSwapCarEngine(car);
Console.WriteLine(car.Engine.ToString());
}
通过引用传递给方法的对象设置为 null
当你通过引用将引用类型作为参数传递给方法(使用 C# 中的 ref 或 out 关键字或者 Visual Basic 中的 ByRef 关键字)时,你可以更改该参数指向的内存位置。
如果通过引用将引用类型传递给某个方法,则该方法可以将引用的类型设置为 null(在 Visual Basic 中为 Nothing)。
在本示例中,NullReferenceFromPassToMethodByRef 中突出显示的行将引发 NullReferenceException,因为对 BadEngineSwapByRef 方法的调用将 stockEngine 变量设置为 null。
public void BadEngineSwapByRef(ref EngineInfo engine)
{
engine = null;
}
public void NullReferenceFromPassToMethodByRef()
{
var stockEngine = new EngineInfo();
stockEngine.Power = "Gas";
stockEngine.Size = 7.0;
BadSwapEngineByRef(ref stockEngine);
Console.WriteLine(stockEngine.ToString());
}
在开发期间查找 null 引用异常的源
使用数据提示、“局部变量”窗口和“监视”窗口来查看变量值
遍历调用堆栈以查找何处未初始化引用变量或未将其设置为 null
将条件断点设置为在对象为 null(在 Visual Basic 中为 Nothing)时停止调试