0

I have a class with this:

public class myDataType
{
   public class GetInvoice
   {
      public string InvoiceID { get; set; }
      public string InvoiceNumber { get; set; }
      public decimal InvoiceAmount { get; set; }
      public List<InvoiceRow> Rows { get; set; } 
   }

   public class InvoiceRow
   {
      public decimal RowQty { get; set; }
      public string RowCode { get; set; }
      public string RowDescription { get; set; }
   }
}

And when I want to add data has th

using static test.myDataType;
...
private void LoadData()
{
   GetInvoice Invoice = new GetInvoice();
   
   Invoice.InvoiceID = "0a8625e5-62f6-4ad7-a8bf-ab04b1158392";
   Invoice.InvoiceNumber = "Inv-001";
   Invoice.InvoiceAmount = 100;
   
   Invoice.Rows.Add(new InvoiceRow { RowQty= 1, RowCode = "C100", RowDescription = "Item C100"});

}

When try to add the row:

Invoice.Rows.Add(new InvoiceRow { RowQty= 1, RowCode = "C100", RowDescription = "Item C100"});

Show me this error "System.NullReferenceException: 'Object reference not set to an instance of an object'"

I think i have a sintax o wrong way to do it Can someone help?

Thanks in advance

  • `Invoice.Rows` is null. Make sure you assign an instance of `List` to it before you try and add any new elements, e.g. with `public List Rows { get; set; } = new List()`. I'll link your question to another one with good advice on debugging NullReferenceExceptions – canton7 Jun 21 '21 at 15:09
  • 1
    Aside from everything else, you probably want the `Rows` property to have a `private set`. This will still allow changes to the list from outside the class, but it will prevent code outside the class from replacing or removing the list out from under you. – Joel Coehoorn Jun 21 '21 at 15:30

2 Answers2

2

It's not a syntax error, you just haven't initialised the list.

With

public List<InvoiceRow> Rows { get; private set; } 

you've declared a place to hold the list, but haven't created the list itself.

(If an analogy helps, imagine you've drawn a line on the wall of your house where you're going to put up a bookshelf, but you haven't actually screwed the shelf to the wall yet - that's the situation your code is in).

If you want the list to always be available you can either initialise it automatically through the property declaration, or in the constructor of the class. Alternatively of course you could leave the calling code to initialise it.

This version just makes it part of the property declaration:

public List<InvoiceRow> Rows { get; private set; } = new List<InvoiceRow>(); 
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
ADyson
  • 57,178
  • 14
  • 51
  • 63
  • 1
    lovely analogy! have an upvote – Mong Zhu Jun 21 '21 at 15:32
  • 1
    @MongZhu why thanks! (I normally extend this analogy by comparing the act of adding items to the list to placing books onto the shelf - occasionally I've seen questions where people have got the impression that instantiting a list somehow also populates it.) – ADyson Jun 21 '21 at 15:52
  • actually because of the adding books part. I kind of extrapolated this on my own. Therefore I found it a great analogy – Mong Zhu Jun 21 '21 at 16:18
1

You need first to initialize list Rows before you add element to it. For example in GetInvoice class you can add:

public List<InvoiceRow> Rows { get; set; } = new List<InvoiceRow>();

List is reference type in C# so it needs to be initialized before being used.

If you want to do that in LoadData() method you can do in this way:

private void LoadData()
    {
        GetInvoice Invoice = new GetInvoice();

        Invoice.InvoiceID = "0a8625e5-62f6-4ad7-a8bf-ab04b1158392";
        Invoice.InvoiceNumber = "Inv-001";
        Invoice.InvoiceAmount = 100;

        Invoice.Rows = new List<InvoiceRow>();
        Invoice.Rows.Add(new InvoiceRow { RowQty = 1, RowCode = "C100", RowDescription = "Item C100" });

    }