20

I have a question about Enumerable.Repeat function.

If I will have a class:

class A
{
//code
}

And I will create an array, of that type objects:

A [] arr = new A[50];

And next, I will want to initialize those objects, calling Enumerable.Repeat:

arr = Enumerable.Repeat(new A(), 50);

Will those objects have the same address in memory? If I will want to check their hash code, for example in that way:

bool theSameHashCode = questions[0].GetHashCode() == questions[1].GetHashCode();

This will return me true, and if I will change one object properties, all other objects will change it too.

So my question is: is that properly way, to initialize reference type objects? If not, then what is a better way?

Michael
  • 449
  • 1
  • 6
  • 13

3 Answers3

31

Using Enumerable.Repeat this way will initialize only one object and return that object every time when you iterate over the result.

Will those objects have the same address in memory?

There is only one object.

To achieve what you want, you can do this:

Enumerable.Range(1, 50).Select(i => new A()).ToArray();

This will return an array of 50 distinct objects of type A.

By the way, the fact that GetHashCode() returns the same value does not imply that the objects are referentially equal (or simply equal, for that matter). Two non-equal objects can have the same hash code.

Kapol
  • 6,383
  • 3
  • 21
  • 46
  • That's weird. I use Enumerable.Repeat to copy an object some dozens of times (so I don't have to copy the values manually) and then edit the properties I'm interested in, and it works flawlessly. So, not really sure what you mean by "one object" – Camilo Terevinto Jul 05 '17 at 22:37
  • 1
    From MSDN: "Generates a sequence that contains one repeated value." - Maybe you were using value types. In that case you would get a copy every single time. – Kapol Jul 05 '17 at 22:40
  • No, they are EF entities with both POCO and nested classes – Camilo Terevinto Jul 05 '17 at 22:41
  • 1
    Hmm... I have just tested this and works as I assumed: `var x = Enumerable.Repeat(new C(), 2); Console.WriteLine(x[0] == x[1]);` prints `true` – Kapol Jul 05 '17 at 22:48
  • 1
    @CamiloTerevinto https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,89605215aab7080f Kapol is correct - it will return the same element n times. – johnnyRose Jul 05 '17 at 23:59
  • @CamiloTerevinto - I've put an answer to show that only one instance is created: https://stackoverflow.com/a/44937849/259769 – Enigmativity Jul 06 '17 at 00:12
7

Just to help clarify for Camilo, here's some test code that shows the issue at hand:

void Main()
{
    var foos = Enumerable.Repeat(new Foo(), 2).ToArray();
    foos[0].Name = "Jack";
    foos[1].Name = "Jill";
    Console.WriteLine(foos[0].Name);    
}

public class Foo
{
    public string Name;
}

This prints "Jill". Thus it shows that Enumerable.Repeat is only creating one instance of the Foo class.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
2

When using the following code to create an array:

var foos = Enumerable.Repeat(new Foo(), 2).ToArray();

The reason why each location in the array is the same is because you are passing an object, and not a function that creates an object, the code above is the same as:

var foo = new Foo();
var foos = Enumerable.Repeat(foo , 2).ToArray();

The reason above also explains why using a Select statement, like in the code below, creates a new object for each entry, because you are passing a function that dictates how each object is created, rather than the object itself.

Enumerable.Range(1, 2).Select(i => new Foo()).ToArray();

I would use a simple for loop to populate an array with new reference types.

Gusty Abra
  • 111
  • 6