这一行(C#)代码
if (!currentLap.S1.HasValue)
给了我
System.NullReferenceException:未将对象引用设置为对象的实例。
如果我确定currentLap变量已实例化(因为它之前使用了几行而且它是一个局部变量)并且它具有以下属性:
private double? _s1;
[DefaultValue(null)]
[JsonConverter(typeof(ShortDoubleConverter))]
public double? S1
{
get { return _s1; }
set { _s1 = value; }
}
怎么可能抛出NullReferenceException?它可以与发布模式下的优化有关吗?
谢谢, 斯特沃
编辑:
这里是完整的方法代码。
public void Update(DriverData driverData)
{
LapInfo currentLap = this.CurrentLap;
if (currentLap != null &&
this.LastDriverData != null &&
driverData.TotalLaps != this.LastDriverData.TotalLaps &&
driverData.InPits &&
driverData.Speed < 10 &&
!this.LastDriverData.InPits)
{
currentLap.Escaped = true;
}
this.LastDriverData = driverData;
if ((currentLap == null || currentLap.Lap != driverData.LapNumber) &&
!this.Laps.TryGetValue(driverData.LapNumber, out currentLap))
{
currentLap = new LapInfo() { Lap = driverData.LapNumber, Parent = this, Class = driverData.Class };
this.Laps.Add(driverData.LapNumber, currentLap);
int lapsCount = 0, completedDriverLaps = 0, cleanLaps = 0;
this.TotalLaps = driverData.TotalLaps;
//if it's not the first lap
if (driverData.TotalLaps > 0)
{
//previous lap
if (this.CurrentLap == null || !this.CurrentLap.Escaped)
{
this.CompletedLaps++;
if (this.CurrentLap == null || !this.CurrentLap.MaxIncident.HasValue)
this.CleanLaps++;
}
}
foreach (DriverLapsInfo laps in this.Parent.LapsByVehicle.Values)
{
lapsCount += laps.TotalLaps;
completedDriverLaps += laps.CompletedLaps;
cleanLaps += laps.CleanLaps;
}
this.Parent.Parent.SetLapsCount(driverData, lapsCount, driverData.Class, completedDriverLaps, cleanLaps);
}
this.CurrentLap = currentLap;
//add incidents
if (driverData.Incidents != null)
{
foreach (IncidentScore incident in driverData.Incidents)
{
this.CurrentLap.MaxIncident = Math.Max(this.CurrentLap.MaxIncident ?? 0, incident.Strength);
this.CurrentLap.Incidents++;
this.Incidents++;
}
}
LapInfo previousLap = null;
if ((this.PreviousLap == null || this.PreviousLap.Lap != driverData.TotalLaps) &&
this.Laps.TryGetValue(driverData.TotalLaps, out previousLap))
{
this.PreviousLap = previousLap;
if (!this.PreviousLap.Date.HasValue)
{
this.PreviousLap.Date = DateTime.UtcNow;
}
}
if (currentLap.Position == 0)
currentLap.Position = driverData.Position;
if (driverData.CurrentS1 > 0)
{
**if (!currentLap.S1.HasValue)**
{
this.UpdateBestS1(driverData.BestS1);
this.Parent.Parent.UpdateBestS1(driverData.BestS1, driverData.UniqueName);
currentLap.UpdateS1(driverData.CurrentS1, driverData);
//reset the best split set at the finish line
if (this.PreviousLap != null && this.PreviousLap.SplitBest < 0)
this.PreviousLap.SplitBest = 0;
}
if (driverData.CurrentS2.HasValue && driverData.CurrentS1.HasValue && !currentLap.S2.HasValue)
{
double s2 = driverData.CurrentS2.Value - driverData.CurrentS1.Value;
this.UpdateBestS2(s2);
this.Parent.Parent.UpdateBestS2(s2, driverData.UniqueName);
currentLap.UpdateS2(s2, driverData);
}
}
if (this.PreviousLap != null)
{
if (driverData.LastLap > 0)
{
if (!this.PreviousLap.S3.HasValue && driverData.LastS2.HasValue)
{
double s3 = driverData.LastLap.Value - driverData.LastS2.Value;
this.UpdateBestS3(s3);
this.Parent.Parent.UpdateBestS3(s3, driverData.UniqueName);
this.PreviousLap.UpdateS3(s3, driverData);
}
if (!this.PreviousLap.LapTime.HasValue)
{
double? bestLap = this.Parent.Parent.BestLap;
this.PreviousLap.UpdateLapTime(driverData, 0);
this.Parent.Parent.UpdateBestLap(this.PreviousLap, driverData.BestLap, driverData);
this.UpdateBestLap(driverData.BestLap, this.PreviousLap);
this.PreviousLap.UpdateLapTime(driverData, bestLap);
}
}
else
{
if (this.PreviousLap.SplitBest.HasValue)
this.PreviousLap.UpdateBestSplit();
if (this.PreviousLap.SplitSelf.HasValue)
this.PreviousLap.UpdateSelfSplit();
}
}
if (driverData.InPits)
{
switch (driverData.Sector)
{
case Sectors.Sector1:
if (previousLap != null)
previousLap.InPits = true;
break;
case Sectors.Sector3:
currentLap.InPits = true;
break;
}
}
//lap to speed
if (currentLap.TopSpeed < driverData.Speed)
{
driverData.TopSpeedLap = driverData.Speed;
currentLap.UpdateTopSpeed(driverData.Speed);
}
else
driverData.TopSpeedLap = currentLap.TopSpeed;
//overall top speed
if (this.TopSpeed < driverData.Speed)
{
driverData.TopSpeed = driverData.Speed;
this.TopSpeed = driverData.Speed;
this.Parent.Parent.UpdateTopSpeed(this.TopSpeed, driverData);
}
else
driverData.TopSpeed = this.TopSpeed;
}
地球上没有任何方法可以使代码进入该行,并且currentLap无效。
还是我疯了? :)
答案 0 :(得分:10)
.HasValue
将不会抛出,但如果a.b.HasValue
为空,则a
将为空。
我怀疑currentLap == null
。我知道你说你确定currentLap
不是空的,但我认为这是最可能的解释。你能发布更多代码吗?
<强>更新强>
感谢发布您的代码。
这不会抛出:
void Main() {
var f = new Foo();
Console.WriteLine (f.S1);
Console.WriteLine (f.S1.HasValue);
}
class Foo {
private double? _s1 = null;
public double? S1 {
get { return _s1; }
set { _s1 = value; }
}
}
你能尝试创造一个最小的复制品吗? (展示问题的最小代码)
答案 1 :(得分:2)
也许看看上一行代码:) - 调试器经常突出显示实际抛出NullReferenceException的那一行之后的下一行。