左手操作数是否首先被破坏?
Is the Left-Hand Operand First broken?
根据Precedence and order of evaluation
left 将在 right 之前被评估。但是,我有一个项目:
int[] df = null; //GetDataFrame()
int xIndex = 12; //GetLearningIndex()
df[0] = 1 % GetLearningIndex();
我意识到,当 GetDataFrame returns null 和 GetLearningIndex returns 零 我得到一个 System.DivideByZeroException
我会根据 System.NullReferenceException
之类的期望......有什么原因吗??
当涉及到数学运算时,左手操作数首先被评估。在你的例子中,你正在调用一个方法,其中 returns 一个值:GetLearningIndex()
,在你使用它的任何数学运算之前总是会计算这个值。
您实际上指的是错误的文档。正如在 the actual one 中提到的,赋值运算符 是 最后评估的。因此,您的方法调用以及数学运算(%
在 DivideByZeroException
.
中的赋值结果之前被评估
此外,赋值运算符是从右到左求值的,这与其他所有从左到右求值的二元运算符形成对比:
Except for the assignment operators, all binary operators are
left-associative, meaning that operations are performed from left to
right. For example, x + y + z is evaluated as (x + y) + z. The
assignment operators and the conditional operator (?:) are
right-associative, meaning that operations are performed from right to
left. For example, x = y = z is evaluated as x = (y = z).
这里有些混乱...首先评估赋值运算符的 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;
执行顺序为:
- 评价
arrayExpression
。没有检查结果是否为非空,但评估表达式本身可能会抛出 NullReferenceException
.
- 评价
indexExpression
。此时不对数组执行边界检查。
- 评价
valueExpression
- 将使用步骤 1 和 2 的结果表示的数组元素设置为步骤 3 的结果。这里 是检查数组引用是否为非空以及执行数组索引有效。
据我所知,目前这方面的规定很糟糕 - 我会提出一个问题,看看我们是否可以在 ECMA C# 5 标准中修复它。
根据Precedence and order of evaluation left 将在 right 之前被评估。但是,我有一个项目:
int[] df = null; //GetDataFrame()
int xIndex = 12; //GetLearningIndex()
df[0] = 1 % GetLearningIndex();
我意识到,当 GetDataFrame returns null 和 GetLearningIndex returns 零 我得到一个 System.DivideByZeroException
我会根据 System.NullReferenceException
之类的期望......有什么原因吗??
当涉及到数学运算时,左手操作数首先被评估。在你的例子中,你正在调用一个方法,其中 returns 一个值:GetLearningIndex()
,在你使用它的任何数学运算之前总是会计算这个值。
您实际上指的是错误的文档。正如在 the actual one 中提到的,赋值运算符 是 最后评估的。因此,您的方法调用以及数学运算(%
在 DivideByZeroException
.
此外,赋值运算符是从右到左求值的,这与其他所有从左到右求值的二元运算符形成对比:
Except for the assignment operators, all binary operators are left-associative, meaning that operations are performed from left to right. For example, x + y + z is evaluated as (x + y) + z. The assignment operators and the conditional operator (?:) are right-associative, meaning that operations are performed from right to left. For example, x = y = z is evaluated as x = (y = z).
这里有些混乱...首先评估赋值运算符的 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;
执行顺序为:
- 评价
arrayExpression
。没有检查结果是否为非空,但评估表达式本身可能会抛出NullReferenceException
. - 评价
indexExpression
。此时不对数组执行边界检查。 - 评价
valueExpression
- 将使用步骤 1 和 2 的结果表示的数组元素设置为步骤 3 的结果。这里 是检查数组引用是否为非空以及执行数组索引有效。
据我所知,目前这方面的规定很糟糕 - 我会提出一个问题,看看我们是否可以在 ECMA C# 5 标准中修复它。