为何CDbl与Double.Parse返回的Double调用ToString结果不同?
演示代码
System.Console.WriteLine($"CDbl: {(CDbl("234.56"))} {(CDbl("234.56")).GetType} {(CDbl("234.56")).ToString("0.0")}") System.Console.WriteLine($"Double.Parse: {(Double.Parse("234.56", usCulture))} {(Double.Parse("234.56", usCulture)).GetType} {(Double.Parse("234.56", usCulture)).ToString("0.0")}")
输出结果
CDbl: 234.56 System.Double 234.6 Double.Parse: 234.56 System.Double 2
问题
第二行输出的是数字的最高位(如输入345.67则输出3),在Visual Studio中鼠标悬停时,第一行的ToString调用显示为Double.ToString,第二行显示为Object.ToString,这是否与输出异常相关?原因是什么?
解答
相关,核心原因是VB.NET的类型推断与Option Strict设置导致的编译解析差异:
类型推断差异:
CDbl函数在VB.NET中直接返回Double类型,编译器能明确识别,因此CDbl("234.56").ToString("0.0")会正确匹配Double.ToString(String)重载,按指定格式输出234.6。而Double.Parse虽实际返回Double,但在默认的Option Strict Off宽松模式下,编译器会将字符串插值中的该表达式隐式推断为Object类型,而非强类型的Double。编译器解析错误:
Object类仅提供无参ToString()和带IFormatProvider参数的ToString()方法,没有接受String参数的重载。在Option Strict Off模式下,编译器会错误地将代码拆解为两步:先调用Object.ToString()得到数字的字符串形式(如"234.56"),再将("0.0")视为字符串索引操作——VB.NET会自动把"0.0"隐式转换为整数0,最终取字符串的第一个字符(即"2"),这就是你看到的“最高位输出”。VS提示的意义:
Visual Studio的悬停提示准确反映了编译时的方法匹配结果:第一行匹配强类型的Double.ToString,第二行因类型推断为Object匹配Object.ToString,这正是输出异常的直接诱因。
解决方法:
开启Option Strict On(可在项目设置中修改,或在代码文件顶部添加Option Strict On),强制编译器进行强类型检查,此时Double.Parse的结果会被明确识别为Double,ToString("0.0")将正确匹配Double.ToString(String)重载,输出正常的格式化结果。
内容的提问来源于stack exchange,提问作者kwc

