左手操作数首先被打破了吗?

时间:2017-04-24 07:17:28

标签: c# operators operator-precedence

根据此here

左边将在右边评估......

但我有一个项目:

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

我意识到,当 GetDataFrame 返回 null GetLearningIndex 返回零时,我会得到一个System.DivideByZeroException我希望根据像System.NullReferenceException ...任何理由??

3 个答案:

答案 0 :(得分:4)

在数学运算方面,首先评估左手操作数。在您的情况下,您正在调用一个返回值GetLearningIndex()的方法,该值将始终在您使用它的任何数学运算之前进行求值。

答案 1 :(得分:2)

这里有一些混淆......首先评估赋值运算符的LHS的 parts 。特别是,表达式df0将在 GetLearningIndex之前计算,但数组元素赋值(包括索引验证)仅在之后 / em>结果已计算完毕。

以下是一个显示更多细节的示例:

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的结果。是数组引用为非空且数组索引有效的检查进行。
  5. 据我所知,目前这个问题很严重 - 我会提出一个问题,看看我们是否可以在ECMA C#5标准中修复它。

答案 2 :(得分:0)

你实际上是在引用错误的文件。正如在the actual one中所提到的那样,最终评估了分配运算符 。因此,在%中的assignemtn屈服之前,会对您的方法调用以及数学运算(DivideByZeroException进行评估。

此外,从左到右评估了从右到左的分配操作符,与从左到右评估的所有其他二进制操作符进行了对比:

  

除赋值运算符外,所有二元运算符都是   左关联,意味着操作从左到右执行   对。例如,x + y + z被评估为(x + y)+ z。该   赋值运算符和条件运算符(?:)是   右关联,意味着操作从右到右执行   剩下。例如,x = y = z被评估为x =(y = z)。