Visual Studio IDE对var关键字的含义感到困惑



考虑以下简单程序:

static class Program
{
  static void Main()
  {
  }
  static void Method(short? x)
  {
    const int y = 50; // note: is Int32, but is const and within Int16 range
    var z = x ?? y;   // note: var keyword used; IDE is confused about the type!
    TakeOnlyInt16(z);
    z.OnThisInt16();
  }
  static void TakeOnlyInt16(short a)
  {
  }
  static void OnThisInt16(this short a)
  {
  }
}

这个程序绝对没有问题,它的编译没有问题。(您可以运行它,可能包括从Main调用Method

但是,Visual Studio IDE 对局部变量的类型有错误的印象 z 。它似乎认为z是一个Int32,而实际上它是一个Int16(又名 short在 C# 中(。该问题至少在三种情况下显示:

  1. 当您将鼠标悬停"在var关键字上(按住(关键字上时,它会在工具提示中显示Int32。这是错误的。

  2. 当您将文本(键盘(光标移动到语句内TakeOnlyInt16(z); Method内部时,它会在此语句的左下角显示一个小提示,提供"生成ProgramTakeOnlyInt16的方法存根"。这是错误的,因为该方法显然已经存在。但它似乎认为已经存在的过载是错误的。 shortint .

  3. 当你在Method里面输入z.(zed dot(时,Int32的成员会出现在智能感知中。请注意,CompareTo 的重载是 Int32 声明的重载,而不是 Int16 声明的重载。此外,当您键入 z. 时,智能感知成员列表中缺少扩展方法。

希望你理解我的解释,没有截图。

问题:这个错误从何而来?是众所周知的吗?它是否也在旧版本的Visual Studio中?

我在VS2013中尝试过这个。

根据 C# 参考,空合并运算符 (??(

用于定义可为 null 的值类型的默认值或 引用类型。如果操作数是 不为空;否则,它将返回正确的操作数。

如果右操作数是int,而左操作数(当不为空时(是short,编译器必须在intshort之间进行选择。而且,由于short可以隐式转换为int(反之亦然(,编译器可以正确确定此表达式的结果是int类型。

还是不服气?为什么不能反过来呢?嗯,让我们看看 C# 语言规范 7.13 是怎么说的:

表达式 a ?? b 的类型取决于操作数上可用的隐式转换。按优先顺序,a的类型??b 是 A0、A 或 B,其中 A 是 a 的类型(假设 a 具有类型(,B 是 b 的类型(假设 b 具有类型(,如果 A 是可为空的类型,则 A0 是 A 的基础类型,否则为 A。

如果您仍然想忽略"可用的隐式转换"部分,因为这可能会导致认为它应该是 A0(短(,让我们继续阅读规范:

具体来说,a ?? b 的处理方式如下:

•如果 A 存在且不是可为 null 的类型或引用类型,则会发生编译时错误。

•如果 b 是动态表达式,则结果类型为动态。在运行时,首先评估 a。如果 a 不为 null,则 a 将转换为动态,这将成为结果。否则,将计算 b,这将成为结果。

•否则,如果 A 存在且为可为空的类型,并且存在从 b 到 A0 的隐式转换,则结果类型为 A0。在运行时,首先评估 a。如果 a 不为 null,则 a 解开包装为类型 A0,这将成为结果。否则,b 被计算并转换为类型 A0,这将成为结果。 注意:情况并非如此,没有从 b(int(到 A0(短(的转换

•否则,如果 A 存在,并且存在从 b 到 A 的隐式转换,则结果类型为 A。在运行时,首先评估 a。如果 a 不为 null,则 a 变为结果。否则,b 被计算并转换为类型 A,这将成为结果。

•否则,如果 b 具有类型 B,并且存在从 a 到 B 的隐式转换,则结果类型为 B。在运行时,首先评估 a。如果 a 不为 null,则 a 被解开包装为类型 A0(如果 A 存在且可为 null(并转换为类型 B,这将成为结果。否则,b 被计算并成为结果。 注意:情况是这种情况

•否则,a 和 b 不兼容,并发生编译时错误。

所以,不,编译器没有错误。你做了一个错误的假设。

编译器看到:

const int y = 50; // note: is Int32, but is const and within Int16 range
var z = x ?? y;   // note: var keyword used; IDE is confused about the type!

并且知道y属于int型,无论它是否const。在这种情况下,假设zInt32,因为它是较大的类型。

如果您想制作 shortz,请尝试:

const int y = 50; // note: is Int32, but is const and within Int16 range
var z = x ?? (short)y;   // note: var keyword used; IDE is confused about the type!

这是一个编译器优化,也许编辑器无法显示。

例如:

short? x = 44;
const int y = int.MaxValue;
var z = x ?? y;
var t = z.GetType(); //Int32

在这种情况下,编译器意识到z最终可能包含不适合 Int16 的值,因此它将z声明为 Int32。

在另一个示例中:

short? x = 44;
const int y = 33;
var z = x ?? y;
var t = z.GetType(); //Int16

编译器意识到z将包含一个始终适合 Int16 的值,因此它将z声明为 Int16

相关内容

  • 没有找到相关文章

最新更新