我有以下C#代码,用1到30之间的随机数填充ArrayList。 我必须将此功能调用25次。 我的代码:
private void getNextTrack()
{
int currentTrack = new Random().Next(1, 30);
if (playlist.Contains(currentTrack) || (topicNo == 8 && currentTrack == 29) || (topicNo == 3 && currentTrack == 14))
getNextTrack(); //If track already exsits or the 2 specified topics dont have that track no. then try again.
else
{
playlist.Add(currentTrack);
++tracksPlayed;
}
}
当函数被初始化调用10-11次时,这很有效,但之后它会立即给出堆栈溢出异常并停止。我不明白为什么递归不是无限的。
答案 0 :(得分:4)
这是因为以下情况:
if
中没有条件满足,else
子句被执行currentTrack
已添加到playlist
getNextTrack
轨道的递归调用已经存在。 请注意,数字将在大多数时间重复,因为您继续使用新的随机生成器。 Random
构造函数的The documentation说:
默认种子值源自系统时钟并具有有限的分辨率。因此,通过调用默认构造函数紧密连续创建的不同Random对象将具有相同的默认种子值,因此将生成相同的随机数集。使用单个Random对象生成所有随机数可以避免此问题。您还可以通过修改系统时钟返回的种子值,然后将此新种子值显式提供给Random(Int32)构造函数来解决此问题。有关更多信息,请参阅Random(Int32)构造函数。
(强调我的)
发生堆栈溢出所需的递归不需要在概念上无限。它足以超过堆栈上的空间限制。这也在the documentation中解释:
执行堆栈溢出错误抛出StackOverflowException,通常是在非常深或无限递归的情况下。
(强调我的)
答案 1 :(得分:4)
堆栈溢出的原因在第1行:
private void getNextTrack() {
int currentTrack = new Random().Next(1, 30); // <- That's the cause
if (playlist.Contains(currentTrack) ...)
getNextTrack();
每次调用方法时重新创建Random
由于Random
从系统计时器初始化,它返回相同
价值一遍又一遍。补救措施:从方法中移动Random
:
// Simplest, not thread-safe
private static Random generator = new Random();
...
private void getNextTrack()
{
int currentTrack = generator.Next(1, 30);
...