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# 代码