Haroun Hajem
Haroun Hajem

Reputation: 5628

Linq query results in the same references when initializing a variable

How is it possible that all the initialized Category = new bool[8] are the same references?

Is this a LINQ bug?

var favorites = (from favorite in dbContext.Favorites
                 where favorite.id == userId
                 select new Favorite()
                            {
                                Title = favorite.Title,
                                Category = new bool[8]
                            }).ToList();

Iterating over the collection and writing to the console log shows me:

 Hash: 3688462
 Hash: 3688462
 Hash: 3688462
 Hash: 3688462
 Hash: 3688462
 Hash: 3688462

Code used to console log:

Debug.WriteLine($"Hash: {favorite.Category.GetHashCode()}");

Did an equality test which was also true

Debug.WriteLine($"Is same: {favorite.Category.Equals(oldFavorite.Category)}");

Upvotes: 2

Views: 70

Answers (2)

Gert Arnold
Gert Arnold

Reputation: 109185

It turns out that EF initializes new instances for each entity if in the initialization "something" is done with a property of the queried entity.

For example, if Category was a class having a FavoriteID property, (and Category an unmapped property in Favorite), this query would initialize one Category instance shared by all Favorites:

 select new Favorite()
            {
                Title = favorite.Title,
                Category = new Category()
            }).ToList();

This query would create n Category instances:

 select new Favorite()
            {
                Title = favorite.Title,
                Category = new Category { FavoriteID = favorite.ID }
            }).ToList();

Knowing this, you can work around the issue in a not too elegant way:

 select new Favorite()
            {
                Title = favorite.Title,
                Category = new bool[]
                { 
                     favorite.ID == -1,
                     false, false, false, false, false, false, false
                }
            }).ToList();

I think a better option is to initialize Category in Favorite's constructor.

I'm not sure if it's a bug or a feature. After all, it also offers an opportunity to create entities all referring to one instance. Well, seems unlikely that this is intended behavior.

Upvotes: 1

Harald Coppoolse
Harald Coppoolse

Reputation: 30474

The code Category = new bool[8] creates an array of 8 Booleans, and initializes it with the default value for a Boolean. So all 8 Booleans in property Category have the same value, probably false.

Your code:

Debug.WriteLine($"Hash: {favorite.Category.GetHashCode()}");

will print the hash code of the complete array of 8 Booleans, which is one int, not eight. Are you sure that you used this code to give you the 8 strings?

One reason that I think you didn't use this code for the output is because of the capital H in Hash, while your output shows a lowercase h in hash

If you have something like:

foreach (bool boolValue in favorite.Category)
{
    Debug.WriteLine($"Hash: {boolValue.GetHashCode()}");
}

then you'll get the same hash code value 8 times, once for each Boolean value in your array.

Upvotes: 0

Related Questions