Home > Software design >  C# possible null reference CS8602
C# possible null reference CS8602

Time:12-01

This should be simple but I can't get ride of this null pointer warning. What can you do? enter image description here

private static List<OrderHeader> orderHeaders = new List<OrderHeader>{...};
      /*Delete order line item from the provided OrderHeader*/
        private void DeleteOrderLine(int orderHeaderIndex, int orderLineIndex)
        {
            if (orderHeaders != null && 
                orderHeaders[orderHeaderIndex] != null && 
                orderHeaders[orderHeaderIndex].OrderLineItems != null &&
                orderHeaders[orderHeaderIndex].OrderLineItems.Count > orderLineIndex
            )
            {
                orderHeaders[orderHeaderIndex].OrderLineItems.RemoveAt(orderLineIndex);             
            } else
            {
                Console.WriteLine("Failed to delete the order line. Please try again");  
            }
        }

Here is second attempt.. still not working.

/*Delete order line item from the provided OrderHeader*/
private void DeleteOrderLine(int orderHeaderIndex, int orderLineIndex)
{
    if (orderHeaders is not null && 
        orderHeaders[orderHeaderIndex] is not null && 
        orderHeaders[orderHeaderIndex].OrderLineItems is not null &&
        orderHeaders[orderHeaderIndex].OrderLineItems.Count > orderLineIndex
    )
    {
        orderHeaders[orderHeaderIndex].OrderLineItems.RemoveAt(orderLineIndex);             
    } else
    {
        Console.WriteLine("Failed to delete the order line. Please try again");  
    }
}

Here's the the order Header definition

public class OrderHeader {

    public enum OrderTypes
    {
        Normal = 0,
        Staff,
        Mechanical,
        Perishable
    }

    public enum OrderStatusTypes
    {
        New = 0,
        Processing,
        Complete
    }

    [Key]
    public string OrderId { get; set; } = string.Empty;

    public OrderTypes OrderType { get; set; }

    public OrderStatusTypes OrderStatus { get; set; }

    public DateTime CreateDate { get; set; } = DateTime.Now;

    public string CustomerName { get; set; } = string.Empty;

    public List<OrderLine>? OrderLineItems { get; set; }
}

Here is the orderLine definition

public class OrderLine { public int LineNumber { get; set; }

public string ProductCode { get; set; } = string.Empty;

public ProductTypes ProductType { get; set; } = 0;

[Column(TypeName = "decimal(18,2)")]
public decimal CostPrice { get; set; }

[Column(TypeName = "decimal(18,2)")]
public decimal SalePrice { get; set; }

public int Quantity { get; set; }

}

CodePudding user response:

It is a common warning when using <Nullable>enable</Nullable>

Since you are checking that orderHeaders[orderHeaderIndex].OrderLineItems is not null then you can use ! operator to indicate that it cannot be null after that check, so try:

private void DeleteOrderLine(int orderHeaderIndex, int orderLineIndex)
{
    if (orderHeaders is not null && 
        orderHeaders[orderHeaderIndex] is not null && 
        orderHeaders[orderHeaderIndex].OrderLineItems is not null &&
        orderHeaders[orderHeaderIndex].OrderLineItems!.Count > orderLineIndex
    )
    {
        orderHeaders[orderHeaderIndex].OrderLineItems!.RemoveAt(orderLineIndex);             
    } else
    {
        Console.WriteLine("Failed to delete the order line. Please try again");  
    }
}

CodePudding user response:

I'd make life simpler by slightly changing your API and then making the analysis simpler for the compiler:

/*Delete order line item from the provided OrderHeader*/
private bool DeleteOrderLine(int orderHeaderIndex, int orderLineIndex)
{
    if(orderHeaders is null) return false;
    var header = orderHeaders[orderHeaderIndex];
    if(header is null) return false;
    var lineItems = header.OrderLineItems;
    if(lineItems is null || lineItems.Count <= orderLineIndex) return false;
    lineItems.RemoveAt(orderLineIndex);
    return true;
}

Note, it's now up to the caller to check the return value and report success to the user, log an error, etc1, 2.

This simplifies the compiler's analysis because it doesn't have to reason about, for instance, whether it's possible for the OrderLineItems property to be capable of modifying the orderHeaders collection such that the next time it's indexed into a different result will be returned.

Note also that it doesn't have to reason about that at all anyway since I only index into the collection once and the compiler knows for certain that local variables don't change their nullability after they've been checked.


1I.e. It's a bit of a smell that it's currently the job of this one method both to change a collection and to know the right way to interact with the users.

2In fact I'd actually probably prefer to do an additional range check on orderHeaderIndex and be throwing ArgumentXxxExceptions rather than returning a bool but that might be too much of a change to accept at this stage

CodePudding user response:

Open your .csproj file and locate the sections that has

<Nullable>enable</Nullable>

Update for more information - disabling it will tell the compiler that you not allowing nullable types on a project scale and if there are null you will handle them

  •  Tags:  
  • c#
  • Related