vb.net x=x+1 与 x +=1

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/808062/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 14:12:23  来源:igfitidea点击:

x=x+1 vs. x +=1

vb.netperformanceoperators

提问by Chad

I'm under the impression that these two commands result in the same end, namely incrementing X by 1 but that the latter is probably more efficient.

我的印象是这两个命令的结果相同,即将 X 增加 1,但后者可能更有效。

If this is not correct, please explain the diff.

如果这不正确,请解释差异。

If it is correct, why should the latter be more efficient? Shouldn't they both compile to the same IL?

如果是正确的,为什么后者更有效?它们不应该编译为相同的 IL 吗?

Thanks.

谢谢。

回答by CoderDennis

From the MSDN library for +=:

MSDN 库中获取 +=

Using this operator is almost the same as specifying result = result + expression, except that result is only evaluated once.

使用此运算符与指定 result = result + 表达式几乎相同,只是结果只计算一次。

So they are not identical and that is why x += 1 will be more efficient.

所以它们不相同,这就是为什么 x += 1 会更有效。

Update:I just noticed that my MSDN Library link was to the JScript page instead of the VB page, which does not contain the same quote.

更新:我刚刚注意到我的 MSDN 库链接指向 JScript 页面而不是VB 页面,它不包含相同的引用。

Therefore upon further research and testing, that answer does not apply to VB.NET. I was wrong. Here is a sample console app:

因此,经过进一步研究和测试,该答案不适用于 VB.NET。我错了。这是一个示例控制台应用程序:

Module Module1

Sub Main()
    Dim x = 0
    Console.WriteLine(PlusEqual1(x))
    Console.WriteLine(Add1(x))
    Console.WriteLine(PlusEqual2(x))
    Console.WriteLine(Add2(x))
    Console.ReadLine()
End Sub

Public Function PlusEqual1(ByVal x As Integer) As Integer
    x += 1
    Return x
End Function

Public Function Add1(ByVal x As Integer) As Integer
    x = x + 1
    Return x
End Function

Public Function PlusEqual2(ByVal x As Integer) As Integer
    x += 2
    Return x
End Function

Public Function Add2(ByVal x As Integer) As Integer
    x = x + 2
    Return x
End Function

End Module

IL for both PlusEqual1 and Add1 are indeed identical:

PlusEqual1 和 Add1 的 IL 确实相同:

.method public static int32 Add1(int32 x) cil managed
{
.maxstack 2
.locals init (
    [0] int32 Add1)
L_0000: nop 
L_0001: ldarg.0 
L_0002: ldc.i4.1 
L_0003: add.ovf 
L_0004: starg.s x
L_0006: ldarg.0 
L_0007: stloc.0 
L_0008: br.s L_000a
L_000a: ldloc.0 
L_000b: ret 
}

The IL for PlusEqual2 and Add2 are nearly identical to that as well:

PlusEqual2 和 Add2 的 IL 也几乎相同:

.method public static int32 Add2(int32 x) cil managed
{ 
.maxstack 2
.locals init (
    [0] int32 Add2)
L_0000: nop 
L_0001: ldarg.0 
L_0002: ldc.i4.2 
L_0003: add.ovf 
L_0004: starg.s x
L_0006: ldarg.0 
L_0007: stloc.0 
L_0008: br.s L_000a
L_000a: ldloc.0 
L_000b: ret 
}

回答by Vinicius Rocha

I wrote a simple console app:

我写了一个简单的控制台应用程序:

static void Main(string[] args)
{
    int i = 0;
    i += 1;
    i = i + 1;
    Console.WriteLine(i);
}

I disassembled it using Reflector and here's what i got:

我使用 Reflector 对其进行了拆卸,这是我得到的:

private static void Main(string[] args)
{
    int i = 0;
    i++;
    i++;
    Console.WriteLine(i);
}

They are the same.

他们是一样的。

回答by z -

they compile to the same, the second is just easier to type.

它们编译成相同的,第二个更容易输入。

回答by Mehrdad Afshari

IMPORTANT:

重要的:

The answers specifying evaluation are certainly correct in terms of what a +=do, in general languages. But in VB.NET, I assume Xspecified in the OP is a variable or a property.

+=在一般语言中,指定评估的答案在做什么方面肯定是正确的。但是在 VB.NET 中,我假设X在 OP 中指定的是一个变量或一个属性。



They'll probably compile to the same IL.

它们可能会编译为相同的 IL。

UPDATE (to address the probably controversy):

更新(以解决可能的争议):

VB.NET is a specification of a programming language. Any compiler that conforms to what's defined in the spec can be a VB.NET implementation. If you edit the source code of the MS VB.NET compiler to generate crappy code for X += 1case, you'll still conform to VB.NET spec (because it didn't say anything about how it's going to work. It just says the effect will be exactly the same, which makes it logical to generate the same code, indeed).

VB.NET 是一种编程语言的规范。任何符合规范中定义的编译器都可以是 VB.NET 实现。如果您编辑 MS VB.NET 编译器的源代码以生成糟糕的X += 1案例代码,您仍然会符合 VB.NET 规范(因为它没有说明它将如何工作。它只是说明了效果将完全相同,这使得生成相同的代码是合乎逻辑的,确实)。

While the compiler is very very likely (and I feel it really does) generate the same code for both, but it's pretty complex piece of software. Heck, you can't even guarantee that a compiler generates the exact same code when the same code is compiled twice!

虽然编译器很可能(我觉得确实如此)为两者生成相同的代码,但它是一个非常复杂的软件。哎呀,当相同的代码被编译两次时,你甚至不能保证编译器生成完全相同的代码!

What you can feel 100% secure to say (unless you know the source code of the compiler intimately) is that a good compiler should generate the same code, performance-wise, which might or might not be the exact same code.

您可以 100% 安全地说(除非您非常了解编译器的源代码)是一个好的编译器应该生成相同的代码,性能方面,这可能是也可能不是完全相同的代码

回答by Mehrdad Afshari

So many speculations! Even the conclusion with the Reflector thingy is not necessarily true because it can do optimizations while dissassembling.

这么多猜测!即使是 Reflector 的结论也不一定正确,因为它可以在反汇编的同时进行优化。

So why does none of you guys just have a look into the IL code? Have a look at the following C# programme:

那么为什么你们中没有人只是查看 IL 代码呢?看看下面的 C# 程序:

static void Main(string[] args)
{
    int x = 2;
    int y = 3;
    x += 1;
    y = y + 1;
    Console.WriteLine(x);
    Console.WriteLine(y);
}

This code snippet compiles to:

此代码片段编译为:

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 x,
[1] int32 y)
// some commands omitted here

IL_0004: ldloc.0
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: stloc.0

IL_0008: ldloc.1
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stloc.1

// some commands omitted here
}

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 x,
[1] int32 y)
// some commands omitted here

IL_0004: ldloc.0
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: stloc.0

IL_0008: ldloc.1
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stloc.1

// some commands omitted here
}

As you can see, it's in fact absolutely the same. And why is it? Because IL's purpose is to tell what to do, not how to. The optimization will be a job of the JIT compiler. Btw it's the same in VB.Net

如您所见,实际上完全相同。为什么?因为 IL 的目的是告诉做什么,而不是如何做。优化将是 JIT 编译器的工作。顺便说一句,它在 VB.Net 中是一样的

回答by Drew Hoskins

On x86, if x is in register eax, they will both result in something like

在 x86 上,如果 x 在寄存器 eax 中,它们都会导致类似

inc eax;

公司

So you're right, after some compilation stage, the IL will be the same.

所以你是对的,在一些编译阶段之后,IL 将是相同的。

There's a whole class of questions like this that can be answered with "trust your optimizer."

有一整类这样的问题可以用“相信你的优化器”来回答。

The famous myth is that
x++;
is less efficient than
++x;
because it has to store a temporary value. If you never use the temporary value, the optimizer will remove that store.

著名的神话是
x++;
效率低于
++x;
因为它必须存储一个临时值。如果您从不使用临时值,优化器将删除该存储。

回答by Luixv

are the same.

是相同的。

x=x+1 

is mathematical seen a contradiction whereas

是数学上的矛盾,而

x+=1

isn't and is light to be typed.

不是,而且很容易打字。

回答by Paul Sonier

They may be the same in VB; they are not necessarily the same in C (where the operator comes from).

它们在 VB 中可能相同;它们在 C 中不一定相同(运算符来自哪里)。

回答by Greg D

  1. Yes, they behave the same.
  2. No, they are probably equally efficient. Optimizers are good at that sort of thing. If you'd like to double check, write the optimized code and view it in reflector.
  1. 是的,他们的行为是一样的。
  2. 不,它们可能同样有效。优化器擅长这类事情。如果您想仔细检查,请编写优化的代码并在反射器中查看。

回答by Macke

The optimizer probably produces the same result, if x is a simple type like int or float.

如果 x 是像 int 或 float 这样的简单类型,优化器可能会产生相同的结果。

If you'd use some other language (limited VB knowledge here, can you overload +=?) where x could be one big honking object, the former creates and extra copy, which can be hundreds of megs. The latter does not.

如果您使用其他语言(有限的 VB 知识,您可以重载 +=?),其中 x 可能是一个大对象,前者会创建一个额外的副本,可能是数百兆。后者没有。