意外行为:列出

时间:2017-01-11 15:41:54

标签: c# list

我今天遇到了一个非常奇怪的问题:

基本上,我想使用以下行将一种类型的数组转换为另一种类型的数组:

DirectoryInfo Source = new DirectoryInfo(@"C:\Orpheus_Music");
FileInfo[] Files = Source.GetFiles("*.mp3");

List<MusicFileModel> FileList = new List<MusicFileModel>();
MusicFileModel temp = new MusicFileModel();

foreach (FileInfo file in Files)
{
    temp.Name = file.Name.ToString();
    temp.Pfad = file.DirectoryName.ToString();

    FileList.Add(temp);

    Debug.WriteLine(temp.Name + ", " + temp.Pfad);
}

Debug.WriteLine("_______________");

foreach (MusicFileModel file in FileList)
{
    Debug.WriteLine(file.Name + ", " + file.Pfad);
}

但是,这不是获取Name和Pfad值的精确副本,而是输出:

01 Rolling in the Deep.mp3, C:\Orpheus_Music
02 Rumour has it.mp3, C:\Orpheus_Music
03 Turning Tables.mp3, C:\Orpheus_Music
04 Don't you remember.mp3, C:\Orpheus_Music
05 Set Fire to the Rain.mp3, C:\Orpheus_Music
06 He won't go.mp3, C:\Orpheus_Music
07 Take it all.mp3, C:\Orpheus_Music
08 I'll be waiting.mp3, C:\Orpheus_Music
09 One and only.mp3, C:\Orpheus_Music
10 Lovesong.mp3, C:\Orpheus_Music
11 Someone like you.mp3, C:\Orpheus_Music
_______________
11 Someone like you.mp3, C:\Orpheus_Music
11 Someone like you.mp3, C:\Orpheus_Music
11 Someone like you.mp3, C:\Orpheus_Music
11 Someone like you.mp3, C:\Orpheus_Music
11 Someone like you.mp3, C:\Orpheus_Music
11 Someone like you.mp3, C:\Orpheus_Music
11 Someone like you.mp3, C:\Orpheus_Music
11 Someone like you.mp3, C:\Orpheus_Music
11 Someone like you.mp3, C:\Orpheus_Music
11 Someone like you.mp3, C:\Orpheus_Music
11 Someone like you.mp3, C:\Orpheus_Music

这里出了什么问题?坦率地说,这似乎是一个初学者的问题,但是,我无法找出究竟是什么导致这一问题。

感谢您的帮助! Michael Heribert

3 个答案:

答案 0 :(得分:10)

你每次都在循环中更新同一个对象,所以你最终得到List<T>中对象的相同副本,最后它只包含在最后一次迭代中设置的值,你必须在循环中实例化新对象,然后将其添加到List<T>

foreach (FileInfo file in Files)
{
    MusicFileModel temp = new MusicFileModel(); // note this

    temp.Name = file.Name.ToString();
    temp.Pfad = file.DirectoryName.ToString();

    FileList.Add(temp);

    Debug.WriteLine(temp.Name + ", " + temp.Pfad);
}

你也可以使用Linq Select()使其变得更简单,但是需要更多操作,因此对于性能而言,每个循环的简单性更好,但你也可以通过以下方式实现:

FileList = Source.GetFiles("*.mp3")
                 .Select(file => new MusicFileModel()
                     {
                        Name = file.Name.ToString(),
                        Pfad = file.DirectoryName.ToString()
                     }).ToList();

答案 1 :(得分:1)

你是对的,这是一个相当新鲜的事情,但当你长时间盯着它时也容易错过

你的问题很简单

 MusicFileModel temp = new MusicFileModel();

        foreach (FileInfo file in Files)
        {
            temp.Name = file.Name.ToString();
            temp.Pfad = file.DirectoryName.ToString();

            FileList.Add(temp);

            Debug.WriteLine(temp.Name + ", " + temp.Pfad);
        }

你创建了一个名为temp的对象,你所做的就是改变它的值并重新添加到列表中,因此它有11个(ish)同一个对象的条目

将第一行移动到循环中。

foreach (FileInfo file in Files)
{
    MusicFileModel temp = new MusicFileModel();
    temp.Name = file.Name.ToString();
    temp.Pfad = file.DirectoryName.ToString();

    FileList.Add(temp);

    Debug.WriteLine(temp.Name + ", " + temp.Pfad);
}

您的代码现在可以按预期工作

答案 2 :(得分:1)

我用两个班轮Linq解决问题的两分钱

List<MusicFileModel> FileList;
FileList = Files.Select(x => new MusicFileModel() 
                 { 
                    Name = x.Name, Pfad = x.DirectoryName
                 }).ToList();

您的错误原因在其他答案中都有详细记录。 正如大家告诉你的那样,更改同一个实例的属性并将其添加到列表n次意味着你的列表有n个对同一个对象的引用。

在我的示例中,Select IEnumerable扩展指示为Files列表中包含的每个FileInfo对象创建一个新的MusicFileModel实例。最后,所有这些实例都在最终的ToList()调用中实现。