R2D2 R2D2 - 1 month ago 8
C# Question

Adding Count of Arrays Together returns 0

I have the following class, where the arrays are populated

public class InternalTag_RelatedObjectsViewModel
{
public Guid[] BranchIDS { get; set; }
public Guid[] CompanyIDS { get; set; }
public Guid[] ContactIDS { get; set; }
public Guid[] DivisionIDS { get; set; }
public Guid[] TenderIDS { get; set; }
public Guid[] ProjectIDS { get; set; }
public Guid[] DocumentIDS { get; set; }
public Guid[] NewsIDS { get; set; }
public Guid[] PhotosIDS { get; set; }

public int Total
{
get
{
return (this.BranchIDS?.Count() ?? 0 + this.CompanyIDS?.Count() ?? 0 + this.ContactIDS?.Count() ?? 0 + this.DivisionIDS?.Count() ?? 0 + this.TenderIDS?.Count() ?? 0 + this.ProjectIDS?.Count() ?? 0 + this.DocumentIDS?.Count() ?? 0 + this.NewsIDS?.Count() ?? 0 + this.PhotosIDS?.Count() ?? 0);
}
}
}


The class is populated and returned by the following method, on another class

static void Main(string[] args)
{
InternalTag_RelatedObjectsViewModel test = new InternalTag_RelatedObjectsViewModel()
{
CompanyIDS = new Guid[] { Guid.NewGuid() },
NewsIDS = new Guid[] { Guid.NewGuid(), Guid.NewGuid() }
};

Console.Write(test.Total);
}


But Total returns 0, Even when some of the arrays have data.
Am I missing something?

Answer Source

You're missing precedence, basically.

It's easier to see what's going on when this is reduced to a minimal example:

using System;

public class Program
{
    public static void Main()
    {
        string[] a = { "x", "y" };
        string[] b = { "x" };

        int first = a?.Length ?? 0 + b?.Length ?? 0;
        int second = (a?.Length ?? 0) + (b?.Length ?? 0);
        Console.WriteLine(first);   // Prints 2
        Console.WriteLine(second);  // Prints 3
    }
}

Obviously 3 is the right answer here. So what's going on?

The ?? operator has lower precedence than +, so first here is equivalent to:

int first = ((a?.Length ?? (0 + b?.Length)) ?? 0;

To split that up:

int? step1 = a?.Length;                // 2
int? step2 = step1 ?? (0 + b?.Length); // 2
int first = step2 ?? 0;

Note how because the result of step1 was non-null, we never end up taking the length of b.

You want to just apply the ?? operator on the result of each nullable length expression, so the brackets around (a?.Length ?? 0) do what you want.