TryParse 适用于 var 但不适用于 C# 中的对象?

Posted

技术标签:

【中文标题】TryParse 适用于 var 但不适用于 C# 中的对象?【英文标题】:TryParse works with var but not with object in 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 调用的结果分配给一个变量,然后在这三种情况下重新使用它。 【参考方案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 参数中使用的变量时更喜欢更明确。

【讨论】:

以上是关于TryParse 适用于 var 但不适用于 C# 中的对象?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 查询适用于 Workbench,但不适用于 C# 代码

HttpClient post call 适用于邮递员,但不适用于 C#

Visual Studio 智能感知/自动更正适用于 C# 术语,但不适用于 Unity

ElasticSearch 索引适用于 REST API,但不适用于 C# 代码

Paypal REST api 调用适用于 cURL,但不适用于 C# 代码

CORS 问题:C# API 请求适用于一个域,但不适用于另一个域