为何VB中Random.Next在If/Case语句内会出现异常行为?
问题描述
编写了一段从数组随机选择字符串的代码,单独运行随机选择逻辑时正常,但放在Select Case或If语句中运行出现异常:
- 燃油类型(Petrol/Diesel)的随机选择功能正常
- 选中Diesel时,仅返回"Electronic Injection Pump",无法获取"Mechanical Injection Pump"
- 选中Petrol时,仅返回"Carburettor"或"Mechanical Fuel Injection",无法获取"Electronic Fuel Injection"
- 将燃油系统选择代码移出分支语句后,可正常返回所有选项;改用
If语句也会出现相同问题 - 数组的
.Count值均符合预期(Diesel对应数组长度2,Petrol对应数组长度3)
原代码如下:
Dim fuelLr = New Random() Dim fuelList() As String = {"Petrol", "Diesel"} Dim fuel = fuelList(fuelLr.Next(0, fuelList.Count)) Dim fuelSystem Select Case fuel Case "Diesel" Dim dieselSystemLr = New Random() Dim dieselSystemList() As String = {"Mechanical Injection Pump", "Electronic Injection Pump"} fuelSystem = dieselSystemList(dieselSystemLr.Next(0, dieselSystemList.Count)) Case "Petrol" Dim petrolSystemLr = New Random() Dim petrolSystemList() As String = {"Carburettor", "Mechanical Fuel Injection", "Electronic Fuel Injection"} fuelSystem = petrolSystemList(petrolSystemLr.Next(0, petrolSystemList.Count)) End Select
问题原因与解决方法
原因
Random类的默认构造函数会以当前系统时钟的毫秒数作为种子值。如果短时间内连续创建多个Random实例,它们会使用完全相同的种子,导致生成的随机序列完全一致:
- 选中Diesel时,新创建的
dieselSystemLr和初始的fuelLr种子相同,而fuelLr已经调用过一次Next(),dieselSystemLr.Next()会取序列中的下一个值,刚好对应Diesel数组的索引1(第二个元素) - 选中Petrol时同理,
petrolSystemLr的随机序列和fuelLr一致,调用Next(0,3)时只会返回0或1,永远到不了索引2
解决方法
只创建一个Random实例,在整个逻辑中复用它,避免短时间内重复创建:
修正后的代码:
' 全局复用一个Random实例 Dim rnd = New Random() Dim fuelList() As String = {"Petrol", "Diesel"} Dim fuel = fuelList(rnd.Next(0, fuelList.Count)) Dim fuelSystem Select Case fuel Case "Diesel" Dim dieselSystemList() As String = {"Mechanical Injection Pump", "Electronic Injection Pump"} fuelSystem = dieselSystemList(rnd.Next(0, dieselSystemList.Count)) Case "Petrol" Dim petrolSystemList() As String = {"Carburettor", "Mechanical Fuel Injection", "Electronic Fuel Injection"} fuelSystem = petrolSystemList(rnd.Next(0, petrolSystemList.Count)) End Select
额外说明
如果是多线程场景,建议使用ThreadLocal(Of Random)来保证线程安全;单线程场景下,复用单个Random实例即可彻底解决当前问题。
内容的提问来源于stack exchange,提问作者user233614
相关产品推荐
相关产品推荐

