Making DefaultIfEmpty return null

91 views Asked by At

I have a class that has 4 fields for nullable doubles:

public class myClass
{
    public double? i1;
    public double? i2;
    public double? i3;
    public double? i4;
}

And I have 4 lists that may hold various values or be empty, for example:

List<double> inputs1 = new List<double> { 1, 2, 3 };
List<double> inputs2 = new List<double> { 4, 5 };
List<double> inputs3 = new List<double> { };
List<double> inputs4 = new List<double> { 8, 9 };

Now, I want to create a list of instances of myClass that hold all possible combinations of these values. To avoid complex foreach loop (in full application there are many more lists and fields in myClass), I am using this LINQ expression:

List<myClass> myObjects = (
    from double? input1 in inputs1.DefaultIfEmpty()
    from double? input2 in inputs2.DefaultIfEmpty()
    from double? input3 in inputs3.DefaultIfEmpty()
    from double? input4 in inputs4.DefaultIfEmpty()
    select new myClass()
    {
       i1 = input1,
       i2 = input2,
       i3 = input3,
       i4 = input4
    }
).ToList();

The intent behind DefaultIfEmpty() is that if any of these lists is empty (like inputs3 in this example), object creation still happens, but corresponding value is not written, and i3 remains null. The problem is that DefaultIfEmpty() appears to return 0 instead, therefore i3 becomes 0 instead of null.

I can't seem to find the right way to "tell" DefaultIfEmpty() to return null when the list is empty. I tried DefaultIfEmpty((double?)null), but compiler doesn't accept such syntax.

Can anyone help?

2

There are 2 answers

4
PajLe On BEST ANSWER

default(double) is 0, but default(double?) is null. So you could use List<double?> instead of List<double>

List<double?> inputs1 = new() { 1, 2, 3 };
List<double?> inputs2 = new() { 4, 5 };
List<double?> inputs3 = new() { };
List<double?> inputs4 = new() { 8, 9 };

If modifying that brings difficulties, you could always cast to double? while processing:

List<myClass> myObjects = (
    from double? input1 in inputs1.Select(x => (double?)x).DefaultIfEmpty()
    from double? input2 in inputs2.Select(x => (double?)x).DefaultIfEmpty()
    from double? input3 in inputs3.Select(x => (double?)x).DefaultIfEmpty()
    from double? input4 in inputs4.Select(x => (double?)x).DefaultIfEmpty()
    select new myClass()
    {
        i1 = input1,
        i2 = input2,
        i3 = input3,
        i4 = input4
    }
).ToList();
0
Charlieface On

You can just use Cast<double?> to change the type of the enumerator to a nullable, so the default becomes null.

List<myClass> myObjects = (
    from double? input1 in inputs1.Cast<double?>.DefaultIfEmpty()
    from double? input2 in inputs2.Cast<double?>.DefaultIfEmpty()
    from double? input3 in inputs3.Cast<double?>.DefaultIfEmpty()
    from double? input4 in inputs4.Cast<double?>.DefaultIfEmpty()
    select new myClass()
    {
       i1 = input1,
       i2 = input2,
       i3 = input3,
       i4 = input4
    }
).ToList();