C# 除非设置断点,否则IEnumerable不会随机移动

C# 除非设置断点,否则IEnumerable不会随机移动,c#,asp.net,asp.net-mvc,linq,asynchronous,C#,Asp.net,Asp.net Mvc,Linq,Asynchronous,我正在尝试使用fisher-yates shuffle来洗牌列表中的元素。但是,除非我在元素应该随机移动的点上放置一个断点,否则元素似乎不会随机移动。我尝试异步执行洗牌,但运气不好(可能是我做错了) 洗牌算法如下所示: // Uses Fisher-Yates shuffle to swap elements public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)

我正在尝试使用fisher-yates shuffle来洗牌列表中的元素。但是,除非我在元素应该随机移动的点上放置一个断点,否则元素似乎不会随机移动。我尝试异步执行洗牌,但运气不好(可能是我做错了)

洗牌算法如下所示:

// Uses Fisher-Yates shuffle to swap elements
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
    {
        Random rng = new Random();
        T[] elements = source.ToArray();

        for (int i = elements.Length - 1; i >= 0; i--)
        {
            int j = rng.Next(i + 1);
            yield return elements[j];
            elements[j] = elements[i];
        }

    }
  [DataContract]
    public class GameData
    {
        [DataMember]
        public int NumLevels { get; set; }

        [DataMember]
        public int? SelectionTime { get; set; }

        [DataMember]
        public IEnumerable<LevelData> Levels { get; set; }
    }

[DataContract]
public class LevelData
{
    [DataMember]
    public int GameLevelId { get; set; }

    [DataMember]
    public int Level { get; set; }

    [DataMember]
    public bool UniqueRounds { get; set; }

    [DataMember]
    public int Rounds { get; set; }

    [DataMember]
    public int NumImages { get; set; }

    [DataMember]
    public IEnumerable<ImageToneData> ImageTones { get; set; }

}


[DataContract]
public class ImageToneData
{
    [DataMember]
    public ImageData Image { get; set; }

    [DataMember]
    public ToneData Tone { get; set; }

    [DataMember]
    public int? Position { get; set; }

}


[DataContract]
public class ImageData
{
    [DataMember]
    public int ImageId { get; set; }

    [DataMember]
    public string ImageFileName { get; set; }
}


[DataContract]
public class ToneData
{

    [DataMember]
    public int ToneId { get; set; }

    [DataMember]
    public string ToneFileName { get; set; }
}
我异步洗牌如下:

imageDataList= imageDataList.Shuffle().ToList();
imageDataList = await Task.Run(() => imageDataList.Shuffle().ToList());
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
{
    Random rng = new Random();
    List<T> elements = source.ToList();

    while (elements.Count > 0)
    {
        int i = rng.Next(elements.Count);
        T item = elements[i];
        elements.RemoveAt(i);
        yield return item;
    }
}
以下是我的代码片段:

GameData gameData = null;
ImageData imageData = null;
ToneData toneData = null;
ImageToneData imageToneData = null;
LevelData levelData = null;

List<ImageData> imageDataList = new List<ImageData>();
List<ToneData> toneDataList = new List<ToneData>();
List<ImageToneData> imageToneDataList = new List<ImageToneData>();
List<LevelData> levelDataList = new List<LevelData>();

 // Add images to a list of ImageData contracts
    foreach (GameImage gameImage in game.GameImages)
    {
        imageData = new ImageData()
        {
            ImageId = gameImage.Image.ImageId,
            ImageFileName = gameImage.Image.ImageFileName
        };

        imageDataList.Add(imageData);

    }

    // Add tones to a list of ToneData contracts
    foreach (GameTone gameTone in game.GameTones)
    {
        toneData = new ToneData()
        {
            ToneId = gameTone.Tone.ToneId,
            ToneFileName = gameTone.Tone.ToneFileName
        };

        toneDataList.Add(toneData);
    }


    //Randomize image and tone association
    imageDataList = imageDataList.Shuffle().ToList();
    toneDataList = toneDataList.Shuffle().ToList();

    // Combine imageData and toneData and assign a position
    for (int i = 0; i < game.NumLevels; i++)
    {
        imageToneData = new ImageToneData()
        {
            Image = imageDataList.ElementAt(i),
            Tone = toneDataList.ElementAt(i),
            Position = (i + 1)
        };

        imageToneDataList.Add(imageToneData);

    }

    foreach (GameLevel level in game.GameLevels)
    {
        //Randomize image/tone (already fixed association)
        imageToneDataList = imageToneDataList.Shuffle().ToList();

        levelData = new LevelData()
        {
            GameLevelId = level.GameLevelId,
            Level = level.Level,
            UniqueRounds = level.UniqueRounds,
            Rounds = level.Rounds,
            NumImages = level.NumImages,
            ImageTones = imageToneDataList.Take(level.NumImages)
        };

        levelDataList.Add(levelData);
    }

gameData = new GameData()
{
    NumLevels = game.NumLevels,
    SelectionTime = game.SelectionTime,
    Levels = levelDataList
};
GameData GameData=null;
ImageData ImageData=null;
ToneData ToneData=null;
ImageToneData ImageToneData=null;
LevelData LevelData=null;
List imageDataList=新列表();
List toneDataList=新列表();
List IMAGETONEDALIST=新列表();
List levelDataList=新列表();
//将图像添加到ImageData合同列表中
foreach(GameImage游戏中的GameImage.GameImage)
{
imageData=新的imageData()
{
ImageId=gameImage.Image.ImageId,
ImageFileName=gameImage.Image.ImageFileName
};
imageDataList.Add(imageData);
}
//将音调添加到音调数据合同列表中
foreach(游戏中的GameTone GameTone.GameTone)
{
toneData=新toneData()
{
ToneId=gameTone.Tone.ToneId,
ToneFileName=gameTone.Tone.ToneFileName
};
toneDataList.Add(toneData);
}
//随机化图像和色调关联
imageDataList=imageDataList.Shuffle().ToList();
toneDataList=toneDataList.Shuffle().ToList();
//组合imageData和toneData并指定位置
for(int i=0;i
我的数据合同如下:

// Uses Fisher-Yates shuffle to swap elements
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
    {
        Random rng = new Random();
        T[] elements = source.ToArray();

        for (int i = elements.Length - 1; i >= 0; i--)
        {
            int j = rng.Next(i + 1);
            yield return elements[j];
            elements[j] = elements[i];
        }

    }
  [DataContract]
    public class GameData
    {
        [DataMember]
        public int NumLevels { get; set; }

        [DataMember]
        public int? SelectionTime { get; set; }

        [DataMember]
        public IEnumerable<LevelData> Levels { get; set; }
    }

[DataContract]
public class LevelData
{
    [DataMember]
    public int GameLevelId { get; set; }

    [DataMember]
    public int Level { get; set; }

    [DataMember]
    public bool UniqueRounds { get; set; }

    [DataMember]
    public int Rounds { get; set; }

    [DataMember]
    public int NumImages { get; set; }

    [DataMember]
    public IEnumerable<ImageToneData> ImageTones { get; set; }

}


[DataContract]
public class ImageToneData
{
    [DataMember]
    public ImageData Image { get; set; }

    [DataMember]
    public ToneData Tone { get; set; }

    [DataMember]
    public int? Position { get; set; }

}


[DataContract]
public class ImageData
{
    [DataMember]
    public int ImageId { get; set; }

    [DataMember]
    public string ImageFileName { get; set; }
}


[DataContract]
public class ToneData
{

    [DataMember]
    public int ToneId { get; set; }

    [DataMember]
    public string ToneFileName { get; set; }
}
[DataContract]
公共类游戏数据
{
[数据成员]
公共int NumLevels{get;set;}
[数据成员]
public int?SelectionTime{get;set;}
[数据成员]
公共IEnumerable级别{get;set;}
}
[数据合同]
公共类级别数据
{
[数据成员]
public int GameLevelId{get;set;}
[数据成员]
公共整数级别{get;set;}
[数据成员]
公共bool UniqueRounds{get;set;}
[数据成员]
公共整数舍入{get;set;}
[数据成员]
公共整数图像{get;set;}
[数据成员]
公共IEnumerable ImageTones{get;set;}
}
[数据合同]
公共类ImageToneData
{
[数据成员]
公共图像数据图像{get;set;}
[数据成员]
公共音调数据音调{get;set;}
[数据成员]
公共int?位置{get;set;}
}
[数据合同]
公共类图像数据
{
[数据成员]
公共int-ImageId{get;set;}
[数据成员]
公共字符串ImageFileName{get;set;}
}
[数据合同]
公共类ToneData
{
[数据成员]
公共int ToneId{get;set;}
[数据成员]
公共字符串ToneFileName{get;set;}
}

非常感谢您的帮助

我会将该方法更改为如下内容:

imageDataList= imageDataList.Shuffle().ToList();
imageDataList = await Task.Run(() => imageDataList.Shuffle().ToList());
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
{
    Random rng = new Random();
    List<T> elements = source.ToList();

    while (elements.Count > 0)
    {
        int i = rng.Next(elements.Count);
        T item = elements[i];
        elements.RemoveAt(i);
        yield return item;
    }
}
公共静态IEnumerable Shuffle(此IEnumerable源代码)
{
随机rng=新随机();
List elements=source.ToList();
而(elements.Count>0)
{
int i=rng.Next(elements.Count);
T项=元素[i];
元素。删除(i);
收益回报项目;
}
}

我猜这两个列表,
imageDataList
toneDataList
,实际上正在被洗牌。我怀疑它们看起来没有被洗牌,因为每次运行该代码时,当您将两个列表合并到
imageToneDataList
中时,同一音调会与上次运行代码时的相同图像配对。这是因为每次调用
Shuffle
方法时,它都会实例化一个新的
Random
Random
使用系统时钟生成其种子。因此,如果您背对背地实例化两个
Random
对象(就像您连续两次调用
Shuffle
所做的那样),则它们具有相同种子的可能性非常高。这意味着它们将生成相同的随机数。这意味着你的两个列表将以完全相同的顺序被洗牌。这就解释了为什么当您只洗牌一个列表时,它看起来工作正常。当您将混洗列表与未混洗到
imageToneDataList
中的列表组合在一起时,您会得到预期的随机结果。这也解释了为什么使用断点时它会起作用。它们会在第一次调用
Shuffle
和第二次调用之间延迟,第二次调用的时间足够长,可以创建带有新种子的
Random
对象


要获得您期望的行为,您需要有一个
Random
的单个实例-可能是包含扩展方法的类中的一个静态字段。

将代码放在一个空的控制台项目中。问题还在吗?不会的。请尝试将
元素
列成一个列表,并在每次生成一个列表时将其删除。@usr我将代码放在一个单独的项目中的一个单独的类中。错误在这里未显示的代码中。把这个代码