2

Apologies if this issue has already come up: I have looked on the questions asked and googled but did not see any explanation.

I am starting to use C#, after nearly 30 years of C, a few months of Java and a couple of years of C++ 15 years ago ... which may explain my perplexity. In C#, if I want an array of int, I can do:

int[] a = new int[10];

At this point, I can access the elements of the array

a[0] = 1; // This is OK

I now have a class (say, SomeClass) and I want to create an array of these:

SomeClass[] o = new SomeClass[10]

I would expect (for symmetry) that I can access the elements of the array, but

a[0].someField = val; // exception, must do a[0] = new SomeClass(); first

So, the first new[]really only allocates 10 pointers, not 10 objects, despite the syntax. I have to repeat that my knowledge of C# is not perfect (:)), so please correct me if I am wrong, but another problem with this (aside from what in my opinion is a confusion between values and references) is memory fragmentation: with C I would have allocated 10 "pointers" (malloc(10 * sizeof (void *));, then allocated the whole area (malloc(10 * sizeof (SomeClass)), then used offsets to initialize the array of pointers to point to the area just malloc'd, minimizing the memory fragmentation ... is there anything similar in C#?

2
  • Instead of pointers, think C++ references. C# classes are called reference types for a reason. You can have an array of class instances just like you can have a std::vector of instances. You have to add something in there before you can access it Commented Sep 29, 2016 at 10:40
  • If you change it to SomeStruct sure, but you can't get an array of "objects themselves" if they are of a reference type. Commented Sep 29, 2016 at 10:45

1 Answer 1

2

Unlike C++ array of class type which has class instances, C# array of class type creates an array of references. This is similar to creating a C++ array of pointers:

SomeClass *o[10] = {0};

Before making any access to o[i] you need to assign it a new object:

cout << o[0]->a;      // ERROR: o[0] is nullptr
o[0] = new SomeClass; // Assign a new object
cout << o[0]->a;      // Works fine

This is the same way that it works in C#: you must assign an object to an array element prior to accessing its attributes.

The reason you don't need to do the same with an int in C# is that int is a value type. Declaring an array of value types populates elements with default values. This applies to user-defined structs as well.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, that's what I thought. I have to get used to the new syntax. In C it is, in my opinion, more explicit whether you refer to "references" (pointers, also addresses) and objects (areas pointed by the addresses).
@MarcoBertoncin You could think of class-typed objects in C# as carrying an implicit asterisk. This streamlined the syntax at the expense of creating a tiny bit of an initial confusion.
@MarcoBertoncin, also, have a look at Value Types vs Reference Types (this is a good start). They have different behavior from this point of view: oversimplifying, a value type variable will never be null. Int (actually an alias for System.Int32 struct) is the first exaample of value type
Thanks all. I understand. As an aside, I completely agree with the implementation (allocate references and objects only after: you may only need a few and this improves memory usage). What about memory fragmentation? (My second point in the original post).
@MarcoBertoncin Since C#'s references are slightly more than pointers, because they must participate in the garbage collection game, C# offers no API for co-locating your references with your objects. The flip side of this is that .NET can deal with fragmentation automatically.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.