Michael Heribert
Michael Heribert

Reputation: 69

Unexpected behaviour: Lists

I encountered a quite strange issue today:

Basically, I want to convert an array of one type into a list of another using the following lines:

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);
}

However, instead of getting an exact copy of the Name and Pfad values, this is the output:

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

What has gone wrong here? This frankly seems to be a beginner's issue, still, I could not find out what exactly causes this.

Thank you for your help! Michael Heribert

Upvotes: 0

Views: 74

Answers (3)

Steve
Steve

Reputation: 216293

My two cents to solve the problem with one liner Linq

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

The reason of your error is all well documented in the other answers. As everyone tells you, changing the properties of the same instance and adding it to the list for n times means that your list has n references to the same object.

In my examples instead the Select IEnumerable extension instruct to create a new instance of MusicFileModel for each FileInfo object contained in the Files list. And finally all those instances are materialized in the final ToList() call.

Upvotes: 1

Ehsan Sajjad
Ehsan Sajjad

Reputation: 62488

you are updating same object every time in the loop, so you end up with the same copy of object in your List<T> and at end it just contains the values that were set in in on the last iteration, you have to instantiate new object inside the loop and then add it in the 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);
}

you can also using Linq Select() to make it more simple, but it would take more operations, so for performance the simple for each loop is better, but you can do it the following way as well:

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

Upvotes: 10

BugFinder
BugFinder

Reputation: 17858

You're right it is a fairly newb thing, but its also easy to miss when you've stared at it too long

Your problem is simple

 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);
        }

You made 1 object called temp and all you did was change its values and re-add it to the list, so it therefore has 11 (ish) entries of the same object

Move that first line into the loop.

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);
}

Your code will now work as you expected

Upvotes: 1

Related Questions