1

Following is the code I wrote Calc[] calculators = new Calc[10]; calculators[0].AddToSum(10); (the corresponding classes and methods are written). But I got "Object reference not set to an instance of an object" exception.Then with some research I got the exception removed by doing following.

for (int i = 0; i < 10; i++)
        {
            calculators[i] = new Calc();
        }  

Can somebody explain why we need to allocate memory again unlike in c/c++. This is how I did it in c++:

Calculator *calc=new Calculator[10]//I know I need to check for std::bad_alloc exception
calculators[0].AddToSum(10); 
delete[] calc;

6 Answers 6

6

In C#, there are reference types, and there are value types. Classes are reference types. When you create a variable of a reference type, you are creating a reference, not an object. The default state of a reference is null. If you want it to refer to an object, you have to explicitly initialize it with new, or assign if from another initialized reference.

C++ does not have this distinction. Every type is a value type (though you can also create references to any type). When you create a variable of a value type, you are creating an object.

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

Comments

1

in new Calc[10] you are allocating and sizing the array. in new Calc() you are creating the actual Calc objects

Comments

1

But you would get that same error with this statement

Calc calc; 
calc.AddToSum(10);

Object is null until you you assign a value.

Calc[] calculators = new Calc[10]; does not allocate.

Based on the answer from Benjamin (+1) it works if Calc is a reference type.
Can you just make Calc a struct?

3 Comments

With the Calc calc; calc.AddToSum(10); code irrespective of type of Calc be struct/class,the code does not compile; results with error - Use of unassigned local variable.But I got the point looks like in c# arrays of userdefined types are reference types and they are like bunch pointers pointing to null.So individual element must be allocated with new.
WRONG. User defined types are NOT limited to reference types. If Calc is a struct then you do not need to initialize the elements in the array.
@Balm thanks for correcting, I tried with making Calc as struct and did Calc[] calculators = new Calc[10]; calculators[0].AddToSum(10); It seemed not throwing exception like it did for class.So struct is a value type and class is reference type.right?
0

I don't think you allocate the memory again, but you still need to instantiate some value for calculators[0].

In your first code-segment, your are trying to call .AddToSum on a value that is Null.

Ps: You could do the following instead, to initialize each Calc from the start:

Calc[] calculators = new Calc[10]{  
                                   new Calc(), 
                                   new Calc(), 
                                   ..., 
                                   // Repeat 10 times to match array length
                                  };

Update: In response to the comments below; Ok, try this then:

calc[] calculators = Enumerable.Repeat(new Calc(), 127).ToArray<Calc>();

3 Comments

that would be horrendous code to maintain. what if you wanted 87 of Calc
Yes, obviously. Just pointing it out as a possibility, and as a contrast the OP to underscore the Null issue. There are clearly better ways to populate an array with many items (this might be fine if you only need two or three items though. Requirements may vary).
@bland I see what you mean, but note that that creates a List, and not an array (although that could be fixed in the same way as in my update, of course..).
0

When you create an array of objects in c++ you allocate memory for all the fields of each object. So if your objects have two integer fields and you make an array of size two, enough memory is allocated to hold four integers.

On the other hand in c# when you make an array of objects you are creating and array of references (pointers to objects). So you cannot store an instance unless you allocate memory for each reference (by using new).

The same thing in c++ would be making an array of pointers, and then you'll have to instantiate each element of your array.

2 Comments

I agree with first two paragraphs;but the third paragraph seems wrong to me.When you do Calc *calc = new Calc[10]; the new takes care of instantiating i.e allocating memory and calling the constructors for all the 10 objects.But in c# as you said it just creates bunch of pointers which individually should be alocated with memory as well constructed.
@ZoomIn: I meant something like this: Calculator** calc = new Calculator*[10];
-2

Your C++ code is also wrong. In C++ you've allocated an array with space for 10 Calculator objects. When you do the operation, it's reading from that (uninitialized) memory, grabbing a value, and adding to it, then writing that back out. But you've got an uninitialized object to start from.

It likely works in C++ because you have an object (Calculator) that doesn't require the constructor to be called. If it had any initialization that required the constructor to be called, it wouldn't work. If you were to use a debugger and put a breakpoint in Calculator constructor, you'll see it's never called.

Anyway, to directly answer the question, this is the way C# works. Allocating an array creates space for the array, but all objects within the array (assuming object types) are null until themselves allocated.

Think of it this way: I create an array to hold 10 objects of Class X. But X has a constructor that takes a string, and I want to call it with a different string for each of those objects. How would one do so without explicitly creating each of those 10 objects and passing the right string to each constructor?

2 Comments

Your information about C++ is incorrect. In C++ variable declaration is object construction. And when you declare an array, or dynamically allocate an array, the constructors for all of the objects in that array are called.
My apologies... you're right. I've been in the C#/Java world so long I'd forgotten that difference. So the simple answer to the original question is that it's simply a difference in the way C++ and Java/C# handle arrays.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.