Первый левый операнд сломан?

В соответствии с этим здесь

левый будет оцениваться до правого...

но у меня есть проект, где:

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

и я понял, когда GetDataFrame возвращает ноль, а GetLearningIndex возвращает ноль, я получаю System.DivideByZeroException Я ожидал бы, согласно как System.NullReferenceException... есть причина почему??

3 ответа

Решение

Здесь есть некоторая путаница... сначала оцениваются части LHS оператора присваивания. В частности, выражения df а также 0 будет оцениваться раньше GetLearningIndex, но назначение элемента массива (включая проверку индекса) происходит только после вычисления результата.

Вот пример, показывающий некоторые дополнительные детали:

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;
    }
}

Итак, в заявлении этой формы:

arrayExpression[indexExpression] = valueExpression;

порядок выполнения:

  1. оценивать arrayExpression, Там нет проверки, что результат не является нулевым, но вычисление выражения может сам бросить NullReferenceException,
  2. оценивать indexExpression, На этом этапе проверка массива не выполняется.
  3. оценивать valueExpression
  4. Установите элемент массива, выраженный с использованием результатов шагов 1 и 2, на результат шага 3. Здесь выполняются проверки, что ссылка на массив не равна нулю и индекс массива действителен.

На данный момент, насколько я могу судить, это плохо указано - я подниму вопрос, чтобы посмотреть, сможем ли мы это исправить в стандарте ECMA C# 5.

Левые операнды вычисляются первыми, когда дело доходит до математических операций. В вашем случае вы вызываете метод, который возвращает значение: GetLearningIndex(), какое значение всегда будет оцениваться перед любой математической операцией, с которой вы его используете.

Вы на самом деле ссылаетесь на неправильный документ. Как уже упоминалось, оператор присваивания, наконец , оценивается. Таким образом, ваш метод-вызов, а также математическая операция (% оценивается до того, как присвоение уступает в DivideByZeroException,

Кроме того, оператор присваивания оценивается справа налево, в отличие от всех других двоичных, которые оцениваются слева направо:

За исключением операторов присваивания, все бинарные операторы являются левоассоциативными, что означает, что операции выполняются слева направо. Например, x + y + z оценивается как (x + y) + z. Операторы присваивания и условный оператор (?:) являются ассоциативными справа, что означает, что операции выполняются справа налево. Например, x = y = z оценивается как x = (y = z).

Другие вопросы по тегам