Yesterday I had to check a reported bug. The error message was “System.ArgumentNullException: ‘Value cannot be null. (Parameter ‘source’)'”. Code is in C#, and as you may think, most of the time, such problems are trivial. Trivial also was the way we could prevent it – to initialize collections.
I started debugging the case. Just in 5 minutes, I saw that that problem was really trivial.
What was the setting, and what was missing?
We have a budget creation. A budget is a single class containing standard budget information (like a year) and a list of budget headings. For simplicity, let’s consider that representation:
public class BudgetHeading
{
public string Name { get; set; }
public decimal Amount { get; set; }
public bool IsModified { get; set; }
public BudgetHeading()
{}
}
public class Budget
{
public int Year { get; set; }
public BudgetStatus Status { get; set; }
public List<BudgetHeading> BudgetHeadings { get; set; }
public Budget(int year, BudgetStatus status)
{
this.Year = year;
this.Status = status;
}
}
Later in the code, we have something like that:
if (budget.Status == BudgetStatus.Approved)
{
budget.BudgetHeadings = budgetRepository.GetLatestBudgetHeadings();
}
As you can see, the problems are piling up, but let’s continue with our case.
A dozen lines bellow, we have the following check:
budget.BudgetHeadings.Where(h => h.IsModified).Any();
We try to check if there are any modified budget headings. Nice, but we not only do not have any headings at all, but our budget headings collection is NULL, so the nice error message is showing:
“System.ArgumentNullException: ‘Value cannot be null. (Parameter ‘source’)'”
The funny thing is that in that case, the problem I am talking about showed another problem – the badly written code for the status check and budget headings initialization. But let’s focus on our topic.
In ninety-nine cases of hundred is a good practice to initialize collections in the constructor. Or something like this:
public class Budget
{
public int Year { get; set; }
public BudgetStatus Status { get; set; }
public List<BudgetHeading> BudgetHeadings { get; set; }
public Budget(int year, BudgetStatus status)
{
this.Year = year;
this.Status = status;
this.BudgetHeadings = new List<BudgetHeading>();
}
}
In cases when you work mainly with DTO objects, you are going to save yourself a lot of headaches. A good practice is to have the initialization also in the default constructor. That way, when an object is created automatically, you will be sure that collections are not NULL.
Of course, you can initialize collections on the spot, but I prefer to do it in the constructor because it looks cleaner.