Is the Left Hand Operand First broken?

according to this here

left will be evaluated before right...

but I have a project where:

int[] df = null;  //GetDataFrame()
int xIndex =  12; //GetLearningIndex()
df[0] = 1 % GetLearningIndex();

and I realized, when GetDataFrame returns null and GetLearningIndex returns zero I get an System.DivideByZeroException I would expect according to the like a System.NullReferenceException ...any reason why??

Jon Skeet
people
quotationmark

There's some confusion here... parts of the LHS of the assignment operator are evaluated first. In particular, the expressions df and 0 will be evaluated before GetLearningIndex, but the array element assignment (including index validation) only occurs after the result has been calculated.

Here's an example showing some more details:

using System;

public class Test
{
    private int[] array = new int[10];

    static void Main()
    {
        Test instance = null;

        // This would throw a NullReferenceException
        // because instance is null at the start of the statement.
        // ExecuteSideEffect never gets called.        
        // instance.array[100] = ExecuteSideEffect(() => instance = new Test());

        instance = new Test();

        // This would throw an IndexOutOfBoundsException
        // because instance.array is evaluated before ExecuteSideEffect.
        // The exception is only thrown when the assignment is performed.
        // instance.array[100] = ExecuteSideEffect(() => instance.array = new int[1000]);

        int index = 5;
        // This modifies array index 5 because index is evaluated
        // before EvaluateSideEffect
        instance.array[index] = ExecuteSideEffect(() => index = 1);
        Console.WriteLine(instance.array[5]); // 10
    }

    private static int ExecuteSideEffect(Action action)
    {
        action();
        return 10;
    }
}

So in a statement of this form:

arrayExpression[indexExpression] = valueExpression;

the execution order is:

  1. Evaluate arrayExpression. There's no check that the result is non-null, but evaluating the expression may itself throw a NullReferenceException.
  2. Evaluate indexExpression. No bounds check is performed on the array at this point.
  3. Evaluate valueExpression
  4. Set the array element expressed using the results of steps 1 and 2 to the result of step 3. This is where the checks that the array reference is non-null and the array index is valid are performed.

This is currently badly specified as far as I can tell - I'll raise an issue to see if we can fix it in the ECMA C# 5 standard.

people

See more on this question at Stackoverflow