不了解具有Nullable类型的预减量运算符行为

时间:2013-05-29 16:11:27

标签: c# nullable

好吧,对于你们中的一些人来说这可能是显而易见的,但我对这个相当简单的代码所带来的行为感到难过:

public static void Main(string[] args)
{
    int? n = 1;
    int i = 1;
    n = ++n - --i;
    Console.WriteLine("Without Nullable<int> n = {0}", n); //outputs n = 2

    n = 1;
    i = 1;
    n = ++n - new Nullable<int>(--i);
    Console.WriteLine("With Nullable<int> n = {0}", n); //outputs n = 3
    Console.ReadKey();
}

我将两个输出都显示为相同且等于2但奇怪的是它们不是。new。有人可以解释原因吗?

编辑:虽然生成这种“怪异”行为的代码无疑是人为设计的,但它确实看起来像C#编译器中的一个错误,虽然看似不重要,但原因似乎是内联{{1正如James最初所指出的那样。但行为不仅限于运营。方法调用的行为方式完全相同,也就是说,只调用一次它们时会被调用两次。

考虑以下重复:

public static void Main()
    {
        int? n = 1;
        int i = 1;
        n = n - new Nullable<int>(sideEffect(ref i));
        Console.WriteLine("With Nullable<int> n = {0}", n);
        Console.ReadKey();
    }

    private static int sideEffect(ref int i)
    {
        Console.WriteLine("sideEffect({0}) called", i);
        return --i;
    }

果然,输出为2,应为1"sideEffect(i) called"打印两次。

4 个答案:

答案 0 :(得分:20)

编辑:团队已经确认这是编译器中的错误。它在罗斯林修复。要解决此问题,请使用强制转换(int?)(--i)来阻止错误显示,或者首先将其明确地转换为Nullable<int>

第一个代码块在反射器中生成以下内容:

int? nullable3;
int? nullable = 1;
int num = 1;
int? nullable2 = nullable;
nullable2 = nullable = nullable2.HasValue
    ? new int?(nullable2.GetValueOrDefault() + 1)    
   : ((int?) (nullable3 = null));
int num2 = --num;
nullable = nullable2.HasValue
    ? new int?(nullable2.GetValueOrDefault() - num2)
    : ((int?) (nullable3 = null));
Console.WriteLine("Without Nullable<int> n = {0}", nullable);

以下第二个:

nullable = 1;
num = 1;
nullable2 = nullable;
nullable2 = nullable = nullable2.HasValue
    ? new int?(nullable2.GetValueOrDefault() + 1)
    : ((int?) (nullable3 = null));
num2 = --num;
nullable = nullable2.HasValue
    ? new int?(nullable2.GetValueOrDefault() - --num)
    : null;
Console.WriteLine("With Nullable<int> n = {0}", nullable);

他们或多或少相同,直到nullable的作业。它运行--num两次,导致它运行2 - -1,结果为3。

对于像i = ~i这样的表达式也是如此,但对于方法调用表达式却没有...

答案 1 :(得分:4)

这是一个非常有趣的问题,我可以看到编译器出现,不止一次地评估-- / ++语句。例如,以下内容:

n = ++n - new Nullable<int>(i++)

会导致n成为0(您期望的那样),但i现在是3(您期望2)。但是,如果我这样做

n = ++n - new Nullable<int>(i);

然后我得到了预期的结果(n = 1i = 1

我只能假设这是以某种方式new Nullable调用相关联。我并不认为这是一个很大的问题,因为这可能不会被认为是你的日常代码,但是,在我看来,这似乎是编译器的一个错误。

答案 2 :(得分:-2)

这是最奇怪的,我试图追踪实际的代码' - '但我不能,但如果你这样做

            n = 1;
        i = 1;
        n = ++n - new Nullable<int>(i--);
        Console.WriteLine("With Nullable<int> n = {0}", n); //outputs n = 2
        Console.ReadKey();

按预期输出。

编辑:全部揭晓:

http://msdn.microsoft.com/en-US/library/wc3z3k8c(v=vs.80).aspx

答案 3 :(得分:-3)

这是因为在这一行:

  n = ++n - new Nullable<int>(--i);

我变成-1和2 - ( - 1)= 3;

它变为负1的原因是你正在创建一个初始化为0然后减去一个(i)的nulluable对象。

您可以在浏览器中将此代码作为* .cshtml文件运行:

@{

    int? m = 1;
    int i = 1;
    m = ++m - --i;
    //MessageBox.Show("Without Nullable<int> n = {0}", n); //outputs n = 2

    int? n = 1;
    i = 1;
    n = ++n - new Nullable<int>(--i);
    //MessageBox.Show("With Nullable<int> n = {0}", n); //outputs n = 3

}

<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <h2>m = @m</h2>
    <h2>n = @n</h2>
</body>
</html>