【问题标题】:TryParse works with var but not with object in C#?TryParse 适用于 var 但不适用于 C# 中的对象?
【发布时间】:2013-12-05 01:35:33
【问题描述】:

看看这个。我想编写以下程序:如果输入双精度或整数,则将其加 1,但如果输入字符串,则在末尾附加一个星号。所以我决定做一个int.TryParse 和一个double.TryParse

Console.WriteLine("Enter something:");
object firstTry = 0;
object secondTry = 0;

bool ifInt = int.TryParse(Console.ReadLine(), out firstTry);
bool ifDouble = Double.TryParse(Console.ReadLine(), out secondTry);

在这种情况下,两个 TryParse 都带有下划线,并且我收到一条消息,指出 object 无法转换为 int,在我看来这是不合逻辑的,因为 object 可以是任何类型...或者,显然,我错了……

附:当我使用var 时我没有这个问题,但我仍然想知道在这种情况下这两种类型之间有什么区别。

【问题讨论】:

  • 任何东西(一切)都是对象,但并非所有对象都是整数、浮点数、字符串或其他任何东西。这就是您收到错误的原因。你需要投射。
  • @KevinM1: casts 和 ref 参数不能很好地结合在一起。
  • 另外,听起来你不想想要两次Console.Readline(你会得到两条不同的线路)。相反,将 one 调用的结果分配给一个变量,然后在这三种情况下重新使用它。

标签: c# object var


【解决方案1】:

int.TryParse 需要int 类型的变量,当您指定var 时,它是隐式类型的,编译器将其视为int,因为已分配值。

见:var (C# Reference)

从 Visual C# 3.0 开始,在方法中声明的变量 范围可以有一个隐式类型 var。隐式类型的本地 变量是强类型的,就像你声明了类型一样 你自己,但编译器决定类型。

var i = 10; // implicitly typed
int i = 10; //explicitly typed

为了让您的double.TryParse 成功,您需要将secondTry 定义为:

var secondTry = 0d; //or 0.0

double secondTry;

【讨论】:

    【解决方案2】:

    var 被称为隐式类型变量。它实际上是 c# 编译器的语法糖。在你的情况下,它实际上是 Int32

    object 版本失败,因为 TryParse 期望 out int 作为参数,但您尝试传递 out object,同样的事情也适用于 Double 版本。

    关于 var 关键字的更多信息可以找到here

    【讨论】:

      【解决方案3】:

      您可以将 int 传递到任何需要对象的地方,因为编译器会自动将 int 作为对象“装箱”,然后改为传递该对象。反之亦然。您不能将对象传递到任何需要 int 的地方。对于值类型,您必须显式转换它,例如:

      object o = 0;
      some_function_that_takes_int((int)o);
      

      如果 o 确实具有 int 值,则此方法可以正常工作。但是,如果您有这样的代码:

      object o = "hello";
      some_function_that_takes_int((int)o);
      

      然后它会编译得很好,但在运行时代码 (int)o 会抛出异常,因为它不能将字符串转换为 int。

      编译器可以自动将 int 装入对象的原因,因为这永远不会失败。它不会反过来做,因为它会在上面演示的代码中失败。

      对于引用参数,例如代码中的 ref 或 out 参数,我认为你甚至不能使用显式转换。这是因为需要 int 值的地址。

      var 不会有任何问题,因为 var 只是告诉编译器自动选择一个类型。在您的情况下,编译器将选择“int”。所以如果你使用 var,一切都是 int。但是,如果您将变量显式定义为“object”,那么您的参数就是“object”并且 TryPase 需要一个“ref int”。它们不兼容,因此无法正常工作。

      希望这会有所帮助。

      【讨论】:

        【解决方案4】:

        object foo; 表单上的声明声明了 object 类型的引用,它可以是 .NET 中的任何内容,因为所有类型都派生自 object

        另一方面,var 只是告诉编译器自己弄清楚它应该在那里写什么的一种方式。所以var foo = 7 将导致foo 变成int。这就是为什么它适用于var 但不适用于object,因为对于var,变量的类型是int

        【讨论】:

          【解决方案5】:

          您的 firstTry 和 secondTry 变量必须匹配它们各自的输出参数:

          int firstTry = 0;
          double secondTry = 0;
          
          bool ifInt = int.TryParse(Console.ReadLine(), out firstTry);
          bool ifDouble = Double.TryParse(Console.ReadLine(), out secondTry);
          

          一般来说,在声明将与 out 参数一起使用的变量时,您必须声明其特定类型。如果你改为写:

          var firstTry = 0;
          var secondTry = 0;
          

          编译器将推断 secondTry 是一个 int - 这不是您想要的。你当然可以写:

          var firstTry = 0;
          var secondTry = 0.0;
          

          现在编译器将为 secondTry 推断 double。但是我发现这样的代码太聪明了,并且在声明 out 参数中使用的变量时更喜欢更明确。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-09-22
            • 2012-03-09
            • 1970-01-01
            • 2017-03-25
            • 1970-01-01
            • 1970-01-01
            • 2017-05-30
            相关资源
            最近更新 更多