目前我正在教授一类C ++程序员C#语言的基础知识。在我们讨论主题运算符时,我使用了C#标准类别的主要,一元等操作符。
其中一位与会者感到困惑,因为在C#标准中,“postfix ++ / - ”已经被置于主要运营商的类别而不是“前缀++ / - ”。她在这种困惑背后的理由是,她宁愿用运算符“前缀++ / - ”来实现C ++运算符“postfix ++ / - ”。换句话说,她宁愿将运算符“prefix ++ / - ”视为主要运算符。 - 我理解她的观点,但我不能给她一个理由。好吧,运营商“postfix ++ / - ”的优先级高于“前缀++ / - ”,但这背后的唯一理由是什么?
规范在“14.2.1运算符优先级和关联性”一节中提到了它。
所以我非常中立的问题:为什么Postfix ++ / - 在C#中被归类为主要操作符? 它有更深层的真相吗?
答案 0 :(得分:2)
我不知道为什么x++
被归类为主要表达,但++x
不归类;虽然我怀疑它会对您编写的代码产生很大影响。同上优先。我想知道后缀是否被认为是主要的,因为它更常用?顺便说一下,注释的C#规范没有任何注释,无论是ECMA版本还是Microsoft C#4版本。 (我无法立即找到我的C#3版本进行检查。)
但是,在实现方面,我会将++
视为一种伪运算符,它由前缀和后缀表达式使用。特别是,当您重载++
运算符时,该重载用于后缀和前缀增量。这与C ++不同,正如stakx在评论中指出的那样。
需要注意的一点是,虽然后递增/后递减表达式必须具有主表达式作为操作数,但是预递增/预递减表达式只需要将一元表达式作为操作数。在这两种情况下,操作数必须被归类为变量,属性访问或索引器访问,所以我不确定是什么实际差异,如果有的话。
编辑:只是为了给出另一点评论,即使它似乎是随意的,我同意当规范说明时它似乎有点奇怪:
主要表达式包括最简单的表达形式
但是,预增量的步骤列表比后增量的步骤列表更短/更简单(因为它不包括“保存值”步骤)。
答案 1 :(得分:2)
由于ECMA标准本身没有定义“主要”运算符是什么,除了优先顺序(即在“一元”之前出现)之外,没有其他意义。单词的选择可能很糟糕。
考虑到在许多C-link语言中,后缀运算符倾向于创建一个临时变量,其中存储表达式的中间结果(请参阅:"Prefer prefix operators over postfix" at Semicolon)。因此,它们与前缀版本根本不同。
尽管如此,我快速检查Mono和Visual Studio如何使用后缀和前缀形式编译for循环,我看到生成的IL代码是相同的。只有当你使用postfix / prefix表达式的值时,它才会转换为不同的IL(仅影响放置'dup'指令的位置),至少对于那些提到的实现。
答案 2 :(得分:1)
不同之处在于 a [i ++]将访问索引为i的元素。
a [++ i]将访问索引为i + 1的元素。
执行[++ i / i ++]后的两种情况
我将是i + 1.
这可能会造成麻烦,因为您无法对参数顺序进行假设
功能(I + +,我+ +,我++)
将增加我3次,但你不知道按顺序。如果最初我是4你也可以 函数(4,5,6)
还有功能(6,5,4) 或功能(6,4,5)。
并且这仍然没有,因为我用作示例本机类型(例如“int”),当你有类时情况变得更糟。
当重载运算符结果没有改变时,改变的是它的优先级。这也会引起麻烦。
因此,在一种情况下,在返回引用之前应用“++”,而在另一种情况下,在“返回”引用之后应用“++”。当你重载它时,最好在返回引用之前应用它(因此++至少从重载的角度来看,比某些东西要好得多。)
采用带有重载++的泛型类(我们有2个项目,foo和bar)
foo = bar ++; //is like writing (foo=bar).operator++();
foo = ++bar; // is like writing foo= (bar.operator++());
并且存在很大差异。特别是当你没有指定引用但是做一些更复杂的引用时,或者在内部你的对象有与浅拷贝VS深拷贝有关的东西。