小心VB.NET中的除运算符/和\

2024-05-04 20:08
文章标签 小心 运算符 net vb

本文主要是介绍小心VB.NET中的除运算符/和\,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转载于:http://www.cnblogs.com/freshman0216/archive/2008/08/27/1276991.html

 VB.NET中除运算符有两种,普通除"/"和整数除"\",如果我们写程序时不注意两者的区别,很容易造成潜在的错误,这种错误很隐蔽,不容易被发现。而且VB.NET中类型转换和C#差别很大,应该引起我们足够的重视,这些看似微不足道的细节却直接关系都我们代码的健壮性。

      1.问题的引出

      下面是开发中遇到问题代码的简化部分,输入大部分数据都没问题,但当输入数字为18时会抛出异常“System.ArgumentException: 偏移量和长度超出数组的界限,于从索引到源集合结尾处的元素数量。在 System.Collections.ArrayList.GetRange(Int32 index, Int32 count)”。是什么原因使ArrayList集合越界呢?这和VB.NET中的除运算符有什么关系呢?当我们理解了VB.NET中两种除的区别以及类型转换(Double—>Integer)的实质后,问题的答案也就不言自明了。

 Sub Main()Console.WriteLine("请输入一个整数:")F1(Console.ReadLine())Console.ReadLine()End SubPublic Sub F1(ByVal times As Integer)Dim list As ArrayList = New ArrayList()'填充数据For i As Integer = 0 To 29list.Add(i)Next'把集合list中元素分成times份进行处理Dim oneTimeNum As Integer = list.Count / timesFor i As Integer = 0 To times - 1Dim length As Integer = oneTimeNumIf i = times - 1 Then'最后一次循环取集合中所有剩余数据length = list.Count - oneTimeNum * iEnd If'实际中这里是启动线程处理,这里简化只是来说明问题F2(list.GetRange(oneTimeNum * i, length))NextEnd SubPrivate Sub F2(ByVal al As ArrayList)'对ArrayList集合al进行处理End Sub


      2.普通除"/"和整数除"\"

      1)普通除:expression1 / expression2

      结果是 expression1 除以 expression2 的完整的商,包括任何余数。执行除法之前,任何整数数值表达式(除数和被除数)都会被扩展为 Double。如果将结果赋给整数数据类型,Visual Basic 会试图将结果从 Double 转换成这种类型。

      举例说明:30 / 18 = 1.6666666666666667,执行除法前被除数30和除数18都扩展为Double类型,结果也为Double类型。

      2)整数除:expression1 \ expression2

      结果是 expression1 除以 expression2 的整数商,它丢弃了所有余数,只保留整数部分(称为截断)。结果数据类型是数值类型,对应于 expression1 和 expression2 的数据类型。值得注意的一点,如果除数或被除数为浮点数,在执行除法前,编译器会采用“四舍六入五成双”的规则将其转换成Long类型,再执行除法。

      举例说明:30 / 18 = 1,只保留结果的整数部分。

      3.VB.NET中的类型转换(Double—>Integer)

      根据第二部分对普通除的解释,当CLR执行Dim oneTimeNum As Integer = 30 / 18时,首先将被除数30和除数18都扩展为Double类型,进行除运算得到Double类型的结果1.6666666666666667,因为要将Double类型数据赋值给Integer类型变量,此时要执行强制类型转换,得到最终结果oneTimeNum = 2(可能很多人和我一样会奇怪结果为什么不是1)。我们从IL代码中查看VB.NET中从Double—>Integer类型转换的实质。

.method public static void  F1(int32 times) cil managed
{// 代码大小       123 (0x7b).maxstack  3.locals init ([0] class [mscorlib]System.Collections.ArrayList list,[1] int32 oneTimeNum,[2] int32 i,[3] int32 V_3,[4] int32 length,[5] int32 VB$t_i4$L0,[6] int32 VB$CG$t_i4$S0,[7] bool VB$CG$t_bool$S0)IL_0000:  nopIL_0001:  newobj     instance void [mscorlib]System.Collections.ArrayList::.ctor()IL_0006:  stloc.0IL_0007:  ldc.i4.0IL_0008:  stloc.2IL_0009:  ldloc.0IL_000a:  ldloc.2IL_000b:  box        [mscorlib]System.Int32IL_0010:  callvirt   instance int32 [mscorlib]System.Collections.ArrayList::Add(object)IL_0015:  popIL_0016:  nopIL_0017:  ldloc.2IL_0018:  ldc.i4.1IL_0019:  add.ovfIL_001a:  stloc.2IL_001b:  ldloc.2IL_001c:  ldc.i4.s   29IL_001e:  stloc.s    VB$CG$t_i4$S0IL_0020:  ldloc.s    VB$CG$t_i4$S0IL_0022:  ble.s      IL_0009IL_0024:  ldloc.0IL_0025:  callvirt   instance int32 [mscorlib]System.Collections.ArrayList::get_Count()IL_002a:  conv.r8IL_002b:  ldarg.0IL_002c:  conv.r8IL_002d:  divIL_002e:  call       float64 [mscorlib]System.Math::Round(float64) //重点看这句IL_0033:  conv.ovf.i4IL_0034:  stloc.1IL_0035:  ldc.i4.0IL_0036:  ldarg.0IL_0037:  ldc.i4.1IL_0038:  sub.ovfIL_0039:  stloc.s    VB$t_i4$L0IL_003b:  stloc.3IL_003c:  br.s       IL_0070IL_003e:  ldloc.1IL_003f:  stloc.s    lengthIL_0041:  ldloc.3IL_0042:  ldarg.0IL_0043:  ldc.i4.1IL_0044:  sub.ovfIL_0045:  ceqIL_0047:  stloc.s    VB$CG$t_bool$S0IL_0049:  ldloc.s    VB$CG$t_bool$S0IL_004b:  brfalse.s  IL_0059IL_004d:  ldloc.0IL_004e:  callvirt   instance int32 [mscorlib]System.Collections.ArrayList::get_Count()IL_0053:  ldloc.1IL_0054:  ldloc.3IL_0055:  mul.ovfIL_0056:  sub.ovfIL_0057:  stloc.s    lengthIL_0059:  nopIL_005a:  ldloc.0IL_005b:  ldloc.1IL_005c:  ldloc.3IL_005d:  mul.ovfIL_005e:  ldloc.s    lengthIL_0060:  callvirt   instance class [mscorlib]System.Collections.ArrayList [mscorlib]System.Collections.ArrayList::GetRange(int32,int32)IL_0065:  call       void VBTest.Module1::F2(class [mscorlib]System.Collections.ArrayList)IL_006a:  nopIL_006b:  nopIL_006c:  ldloc.3IL_006d:  ldc.i4.1IL_006e:  add.ovfIL_006f:  stloc.3IL_0070:  ldloc.3IL_0071:  ldloc.s    VB$t_i4$L0IL_0073:  stloc.s    VB$CG$t_i4$S0IL_0075:  ldloc.s    VB$CG$t_i4$S0IL_0077:  ble.s      IL_003eIL_0079:  nopIL_007a:  ret
} // end of method Module1::F1


      从IL代码可以看出,VB.NET中执行类型转换实际上是调用的函数[mscorlib]System.Math::Round(float64),MSDN中对这个函数的解释:将双精度浮点值舍入为最接近的整数,如果参数为两个整数的中值,这两个整数一个为偶数,另一个为奇数,则返回偶数(也就是我们常说的“四舍六入五成双”)。
      现在,可以很好的解释文章开始提出的问题了:由于输入18时,oneTimeNum的值为2,当循环到第16次时i = 15,此时执行list.GetRange(oneTimeNum * i, length)list.GetRange(30,2),已经超出了list的长度范围,所以会抛出异常。

      4.C#和VB.NET的区别

      1)C#中的除运算"/"符相当于VB.NET的整数除"\"运算符;
      2)C#中从Double—>Integer类型转换必须要采用显示方式,且转换规则为直接舍弃小数位。

      总结这次出现问题的根源是用C#语法去推断VB.NET语法,因为接触C#较早,而C#和VB.NET语法又大同小异,忽略了对VB.NET基本语法的学习,以后应多注意两种语言的差别,尽量减少类似的错误。还有一点需要注意,遇到问题的时候多查MSDN,似乎现在都习惯从网上寻求答案,但网上关于VB.NET除运算符的内容并不多,找了半天,才发现MSDN上写的很详细,我想查找资料的顺序应该是:MSDN—>CNBlogs找找看—>Google/Baidu。


这篇关于小心VB.NET中的除运算符/和\的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/960008

相关文章

MySQL中比较运算符的具体使用

《MySQL中比较运算符的具体使用》本文介绍了SQL中常用的符号类型和非符号类型运算符,符号类型运算符包括等于(=)、安全等于(=)、不等于(/!=)、大小比较(,=,,=)等,感兴趣的可以了解一下... 目录符号类型运算符1. 等于运算符=2. 安全等于运算符<=>3. 不等于运算符<>或!=4. 小于运

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题

《解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题》:本文主要介绍解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4... 目录未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘打开pom.XM

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

使用easy connect之后,maven无法使用,原来需要配置-Djava.net.preferIPv4Stack=true问题

《使用easyconnect之后,maven无法使用,原来需要配置-Djava.net.preferIPv4Stack=true问题》:本文主要介绍使用easyconnect之后,maven无法... 目录使用easGWowCy connect之后,maven无法使用,原来需要配置-DJava.net.pr

Kotlin运算符重载函数及作用场景

《Kotlin运算符重载函数及作用场景》在Kotlin里,运算符重载函数允许为自定义类型重新定义现有的运算符(如+-…)行为,从而让自定义类型能像内置类型那样使用运算符,本文给大家介绍Kotlin运算... 目录基本语法作用场景类对象数据类型接口注意事项在 Kotlin 里,运算符重载函数允许为自定义类型重

在.NET平台使用C#为PDF添加各种类型的表单域的方法

《在.NET平台使用C#为PDF添加各种类型的表单域的方法》在日常办公系统开发中,涉及PDF处理相关的开发时,生成可填写的PDF表单是一种常见需求,与静态PDF不同,带有**表单域的文档支持用户直接在... 目录引言使用 PdfTextBoxField 添加文本输入域使用 PdfComboBoxField

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

Java逻辑运算符之&&、|| 与&、 |的区别及应用

《Java逻辑运算符之&&、||与&、|的区别及应用》:本文主要介绍Java逻辑运算符之&&、||与&、|的区别及应用的相关资料,分别是&&、||与&、|,并探讨了它们在不同应用场景中... 目录前言一、基本概念与运算符介绍二、短路与与非短路与:&& 与 & 的区别1. &&:短路与(AND)2. &:非短

基于.NET编写工具类解决JSON乱码问题

《基于.NET编写工具类解决JSON乱码问题》在开发过程中,我们经常会遇到JSON数据处理的问题,尤其是在数据传输和解析过程中,很容易出现编码错误导致的乱码问题,下面我们就来编写一个.NET工具类来解... 目录问题背景核心原理工具类实现使用示例总结在开发过程中,我们经常会遇到jsON数据处理的问题,尤其是