C# 递增 ToString

发布于 2024-12-11 02:29:05 字数 487 浏览 4 评论 0原文

我在 C#/WPF 中添加了意外行为

    private void ButtonUp_Click(object sender, RoutedEventArgs e)
    {
        int quant;
        if( int.TryParse(Qnt.Text, out quant))
        {
            string s = ((quant++).ToString());
            Qnt.Text = s;
        }
    }

因此,如果我将 Quant 设为 1,Quant 将增加到 2。但是 s 字符串将为 1。这是优先级问题吗?

编辑:

我将其重写为:

            quant++;
            Qnt.Text = quant.ToString();

现在这按我的预期工作。

I add an unexpected behaviour from C#/WPF

    private void ButtonUp_Click(object sender, RoutedEventArgs e)
    {
        int quant;
        if( int.TryParse(Qnt.Text, out quant))
        {
            string s = ((quant++).ToString());
            Qnt.Text = s;
        }
    }

So, if I get quant as 1, quant will be incremented to 2. But the s string will be 1. Is this a question of precedence?

EDIT:

I re-wrote this as:

            quant++;
            Qnt.Text = quant.ToString();

and now this works as I expected.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

悲念泪 2024-12-18 02:29:05

您正在使用post-增量运算符。这会计算出原始值,然后递增。要在一行中执行您想要的操作,您可以使用增量运算符。

(++quant).ToString();

但更好的是避免所有这些陷阱并这样做:

quant++;
string s = quant.ToString();

对于第一个版本,您必须考虑事情发生的顺序。在第二个版本中不需要思考。始终更重视代码的清晰度而不是简洁性。

人们很容易相信单行版本在某种程度上更快,但事实并非如此。在 20 世纪 70 年代的 C 系统中,这可能是正确的,但即便如此,我对此表示怀疑。

You are using the post-increment operator. This evalutates to the original value, and then increments. To do what you want in a one-liner you can use the pre-increment operator instead.

(++quant).ToString();

But even better would be to avoid all such pitfalls and do it like this:

quant++;
string s = quant.ToString();

With the first version you have to think about the order in which things happen. In the second version no thought is required. Always value code clarity more highly than conciseness.

It's easy to believe that the one-line version is somehow faster, but that's not true. It might have been true back in the day in 1970s C systems, but even then that I doubt.

飞烟轻若梦 2024-12-18 02:29:05

问题是您使用的是后增量而不是前增量...但是为什么您要编写这段复杂的代码呢?只需将副作用(增量)和 ToString 调用分开:

if (int.TryParse(Qnt.Text, out quant))
{
    quant++;
    Qnt.Text = quant.ToString();
}

或者甚至放弃实际的增量,因为您不会再次读取该值:

if (int.TryParse(Qnt.Text, out quant))
{
    Qnt.Text = (quant + 1).ToString();
}

在可能的情况下,避免em> 在其他表达式中间使用复合赋值。它通常会导致疼痛。

此外,感觉所有这些解析和格式化都隐藏了真实的模型,也就是说,某处应该有一个 int 属性,这可能反映在 UI 中。例如:

private void ButtonUp_Click(object sender, RoutedEventArgs e)
{
    // This is an int property
    Quantity++;
    // Now reflect the change in the UI. Ideally, do this through binding
    // instead.
    Qnt.Text = Quantity.ToString();
}

The problem is that you're using a post-increment instead of a pre-increment... but why would you want to write this convoluted code? Just separate out the side-effect (incrementing) and the ToString call:

if (int.TryParse(Qnt.Text, out quant))
{
    quant++;
    Qnt.Text = quant.ToString();
}

Or even forego the actual increment given that you're not going to read the value again:

if (int.TryParse(Qnt.Text, out quant))
{
    Qnt.Text = (quant + 1).ToString();
}

Where possible, avoid using compound assignment in the middle of other expressions. It generally leads to pain.

Additionally, it feels like all this parsing and formatting is hiding the real model, which is that there should be an int property somewhere, which might be reflected in the UI. For example:

private void ButtonUp_Click(object sender, RoutedEventArgs e)
{
    // This is an int property
    Quantity++;
    // Now reflect the change in the UI. Ideally, do this through binding
    // instead.
    Qnt.Text = Quantity.ToString();
}
心是晴朗的。 2024-12-18 02:29:05

现在我会做一些不应该做的事情...我会尝试简化 Eric Lippert 在这里写的内容 i++ 和 ++i 之间有什么区别? 我希望我没有写太多错误的东西:-)

现在...前自增和后自增运算符的作用是什么?简化并忽略中间完成的所有复制(并记住它们在多线程环境中不是原子运算符):

它们都是表达式(例如i + 1< /code>)返回结果(如 i + 1),但有副作用(与 i + 1 不同)。副作用是它们增加了变量i。最大的问题是“一切按什么顺序发生?”答案很简单:

  • i并返回i
  • 预增量++i:增量增量i++:增量i并返回i

现在...重要的部分是增量 i 总是首先发生。然后返回一个值(旧的或新的)。

让我们举一个例子(Lippert 的例子相当复杂。我会做一个不同的、更简单的例子,虽然不是那么完整,但足以检查我之前说的顺序是否正确)(技术上)我将举两个例子)

示例 1:

unchecked
{
    int i = Int32.MaxValue;
    Console.WriteLine("Hello! I'm trying to do my work here {0}", i++);
    Console.WriteLine("Work done {1}", i);
}

示例 2:

checked
{
    int i = Int32.MaxValue;
    Console.WriteLine("Hello! I'm trying to do my work here {0}", i++);
    Console.WriteLine("Work done {1}", i);
}

checked 表示如果存在溢出,将抛出异常 (OverflowException)。 unchecked 意味着相同的操作不会抛出异常。 Int32.MaxValue + 1 肯定会溢出。如果选中,则会出现异常,如果未选中,则i将变为-1。

让我们尝试运行第一个代码段。结果:

Hello! I'm trying to do my work here 2147483647
Work done -1

好的...i 增加了,但 Console.WriteLine 收到了旧值 (Int32.MaxValue == 2147483647)。从这个例子中我们无法确定后递增和调用Console.WriteLine的顺序。

让我们尝试运行第二个代码段。结果:

System.OverflowException: Arithmetic operation resulted in an overflow.

好的...很明显,首先执行了后置增量,引发了异常,然后显然 Console.WriteLine 没有执行(因为程序结束了)。

所以我们知道我说的顺序是正确的。

现在。你应该从这个例子中学到什么?这和我很多年前学到的一样。 C 和 C# 中的前后增量非常适合混淆代码竞赛。它们不适用于许多其他事情(但请注意,C++ 不同!)。从那次教训中我了解到,可以自由使用后自增的地方正好有两个,可以自由使用前自增的地方正好有零个。

“安全”后增量

for (int i = 0; i < x; i++)

i++; // Written alone. Nothing else on the same line but a comment if necessary.

“安全”前增量

(nothing)

Now I'll do something that shouldn't be done... I'll try to simplify what Eric Lippert wrote here What is the difference between i++ and ++i? I hope I'm not writing anything too much wrong :-)

Now... What does the pre-increment and post-increment operators do? Simplifying and ignoring all the copy that are done in-between (and remembering that they aren't atomic operators in multi-threaded environments):

both of them are expressions (like i + 1) that return a result (like i + 1) but that have a side-effect (unlike i + 1). The side-effect is that they increment the variable i. The big question is "in which order everything happens?" The answer is quite simple:

  • pre increment ++i: increments i and returns the new value of i
  • post increment i++: increments i and returns the old value of i

Now... The important part is that the increments i always happens first. Then a value (the old or the new) is returned.

Let's make an example (the example of Lippert is quite complex. I'll make a different, more simple example, that isn't as much complete but that is enough to check if the order I said before is right or not) (technically I'll make two examples)

Example 1:

unchecked
{
    int i = Int32.MaxValue;
    Console.WriteLine("Hello! I'm trying to do my work here {0}", i++);
    Console.WriteLine("Work done {1}", i);
}

Example 2:

checked
{
    int i = Int32.MaxValue;
    Console.WriteLine("Hello! I'm trying to do my work here {0}", i++);
    Console.WriteLine("Work done {1}", i);
}

checked means that if there is an overflow an exception (OverflowException) will be thrown. unchecked means that the same operation won't throw an exception. Int32.MaxValue + 1 surely will overflow. With checked there will be an exception, with unchecked i will become -1.

Let's try running the first code piece. Result:

Hello! I'm trying to do my work here 2147483647
Work done -1

Ok... The i was incremented but the Console.WriteLine received the old value (Int32.MaxValue == 2147483647). From this example we can't determine the order of the post-increment and of the calling of Console.WriteLine.

Let's try running the second code piece. Result:

System.OverflowException: Arithmetic operation resulted in an overflow.

Ok... It's quite clear that first the post-increment was executed, caused an exception, and then clearly the Console.WriteLine wasn't executed (because the program ended).

So we know that the order I said is the right one.

Now. What should you learn from this example? The same thing I learned many years ago. Pre and post increments in C and C# are good for obfuscated code contests. They aren't good for many other things (but note that C++ is different!). From that lesson I learned that there are exactly two places where you can use post-increment freely, and there are exactly zero places where you can use pre-increment freely.

"Safe" post-increment

for (int i = 0; i < x; i++)

and

i++; // Written alone. Nothing else on the same line but a comment if necessary.

"Safe" pre-increment

(nothing)
聽兲甴掵 2024-12-18 02:29:05

在这种情况下,首先将调用 quant.ToString(),然后 quant 将递增。

如果您编写 ((++quant).ToString()) ,第一步将递增 quant,然后调用 quant.ToString()

In this case, first quant.ToString() will be called and then quant will be incremented.

If you write ((++quant).ToString()) the first step will be incrementing quant and then quant.ToString() will be called.

豆芽 2024-12-18 02:29:05

string s = ((quant++).ToString());

可以分发为

在递增之前使用 quant 调用 toString() 方法,然后

执行赋值运算符,然后

增加 `quant'

尝试使用 ++quant。

string s = ((quant++).ToString());

can be distributed as

use quant for toString() method call before incrementing, and then

execute assignment operator, and then

increment `quant'

try with ++quant.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文