6

Dysfunctional Example:

public struct MyStruct { public int i, j; }

static readonly MyStruct [] myTable = new MyStruct [3] 
{
    {0, 0}, {1, 1}, {2, 2}
}

I know that this code doesn't work. Now how do I write this down please (proper syntax)?

The thought behind this is the following. Afaik the elements of arrays of struct are value types, so myTable points to a memory location containing three MyStruct objects (and not to a memory location containing three (uninitialized) pointers to MyStruct objects).

So how do I go about initializing those MyStruct objects, what would be the right syntax? I don't have to allocate them anymore, right?

Razzupaltuff
  • 2,250
  • 2
  • 21
  • 37
  • See http://stackoverflow.com/questions/1109805/declaring-a-const-double-in-c – JeremyDWill Aug 16 '11 at 14:01
  • possible duplicate of [Initializing an Array of Structs in C#](http://stackoverflow.com/questions/309496/initializing-an-array-of-structs-in-c) –  Aug 16 '11 at 14:02
  • @Code Monkey: I had read that question and the answers, but that hasn't helped me a bit. – Razzupaltuff Aug 16 '11 at 14:09
  • @JeremyDWill: The problem is not "const" - I gladly changed this to "static readonly". The problem is the syntax to initialize an array of structs. – Razzupaltuff Aug 16 '11 at 14:10
  • @karx: So why not cite in your question ? Your question is a duplicate as it stands right now. –  Aug 16 '11 at 14:10
  • I have edited the question quite a bit. You still didn't read it, did you? – Razzupaltuff Aug 16 '11 at 14:13
  • 2
    @karx11erx - as originally written, CONST *was* a problem. Now that you have changed the question, my comment is no longer applicable, but at the time I made the comment, it definitely *was* applicable. – JeremyDWill Aug 16 '11 at 15:07

2 Answers2

10

The problem you are facing has nothing to do with using a struct as the array type. Your syntax would also be invalid if you would use a class.

This works:

MyStruct [] myTable = new MyStruct [] 
{
    new MyStruct { i = 0, j = 0 },
    new MyStruct { i = 1, j = 1 },
    new MyStruct { i = 2, j = 2 }
};

You have to use collection initializers together with object initializers.

As collection initializers and object initializers are just syntactic sugar, this is equivalent to

MyStruct [] myTable = new MyStruct[3]; 
var tmp = new MyStruct();
tmp.i = 0;
tmp.j = 0;
myTable[0] = tmp;
// and so on...

What you really want with an array of structs is this:

MyStruct [] myTable = new MyStruct[3]; 
myTable[0].i = 0;
myTable[0].j = 0;
// and so on...

But this can't be achieved using the short hand initializer syntax.

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • And that invalid syntax involves structs... The OP said it didn't work. – H H Aug 16 '11 at 13:54
  • @Henk: I revised that sentence, so it says what I really meant. – Daniel Hilgarth Aug 16 '11 at 13:56
  • Well, I thought that the elements of myTable are value and not reference types (i.e. myTable points to a memory location actually containing 3 MyStruct objects, and not 3 pointers to MyStruct objects). So why do I have to allocate the structs in the initialization of myTable? Is this just syntax, and the C# compiler will simply initialize the 3 MyStruct objects, or will it actually allocate 3 MyStruct objects on the heap? – Razzupaltuff Aug 16 '11 at 13:56
  • 1
    I know. That's why I wrote "*dysfunctional*". – Razzupaltuff Aug 16 '11 at 13:59
  • @karx11erx: I extended my answer a bit, to answer on your "is this just syntax" question. However, I don't really know about whether objects will be created on the stack or heap for this. And maybe, [you really shouldn't care](http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx). – Daniel Hilgarth Aug 16 '11 at 14:03
  • Daniel, this has nothing to do with the stack or the heap. Value types declared inside functions go on the stack, value types declared in some global array go on the heap. But again, that was not the question. – Razzupaltuff Aug 16 '11 at 14:12
  • @karl11erx .Arrays are reference types. So the structure array is going to be on the heap along with the 3 structure elements you created inside the array. – Ashley John Aug 16 '11 at 14:31
  • Consider a variable of some struct type declared in a function - it will reside on the stack. – Razzupaltuff Aug 17 '11 at 20:51
8

You need to use actual instances of your MyStruct, which you can create with the new keyword.

This should work...

struct MyStruct 
{ 
   int i, j; 

   public MyStruct(int a, int b)
   {
      i = a;
      j = b;
   }
}

static MyStruct[] myTable = new MyStruct[3]
{
   new MyStruct(0, 0),
   new MyStruct(1, 1),
   new MyStruct(2, 2)
};
musefan
  • 47,875
  • 21
  • 135
  • 185
  • Yeah, there are syntax errors, but that's because I don't know how to write the shorthand initialization of the struct objects in an array of struct. I have edited my question to make the critical issue clearer. – Razzupaltuff Aug 16 '11 at 14:05
  • Why do I need to call "new MyStruct ()" for each array element when the array elements are value types? – Razzupaltuff Aug 16 '11 at 14:21
  • @karl11erx. you need to call new MyStruct() to call the constuctor explicitly.that is just a syntax for calling it – Ashley John Aug 16 '11 at 14:36
  • @karl11erx, you have to initialise them with the constructor (new MyStruct()) because the array will only take data types of MyStruct and the constructor is currently your only way to create an object of type MyStruct – musefan Aug 16 '11 at 14:41
  • Oh! So what really happens is that a temporary MyStruct object is created and copied to the MyStruct object in the array, right! – Razzupaltuff Aug 16 '11 at 14:42
  • @karx11erx, not quite, there is no temporary. The MyStruct you create is the MyStruct object used in the array. In fact, you don't even need to specify the array size in this case (which is the "3" part) as the array initialiser will handle this for you – musefan Aug 16 '11 at 14:53
  • So it is just a "syntactical workaround" to do the initialization? – Razzupaltuff Aug 16 '11 at 23:53
  • @musefan There is a temporary and a copy is made. You can test this by having a constructor that contains `i = 42; throw new Exception();`. You'll notice that i has not been assigned, or rather, that the struct has not been copied. OP may have used C++ before, where in place initialization is possible. Not so in C#. – Kris Vandermotten Oct 25 '13 at 13:48