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;
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.
in new Calc[10] you are allocating and sizing the array. in new Calc() you are creating the actual Calc objects
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?
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>();
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.
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?
Related
I am developing a game where 2 players each have many objects from a class called UnitObject, each of which can be on a different Army.
Right now, the player class has a List of UnitObjects and at the same time, each Army has its own List for storing units that belong to it. I am new to c# and I am wondering if, when having hundreds of units, it would be better to have the player have a Dictionary<int, UnitObject> with the int being the id of said unit, so that other classes can have just a List of integers for reference. Do the UnitObjects in the Army duplicate the memory use of the ones in the Player or is it just a reference?
My code could be (very) simplified to:
UnitObject unit = new UnitObject();
army.units.Add(unit)
player.units.Add(unit)
This is an over simplification, my classes have other classes they belong to and is not as simple as to make the player have a list of armies or so. I am just wondering if by doing this, i am using double memory for each object.
UnitObject is a reference type, unlike s struct or [most] primitive objects such as int, which are value types.
Reference objects are allocated independently, either on the the stack or the heap (depending). They are passed by reference: when you add an instance of a reference type (such as an instance of your UnitObject) to a collection, what it added is a reference to the actual object itself. A reference is a single processor word (32- or 64-bit, depending on processor architecture). It's not a pointer, more like a pointer to a pointer, to allow the allocated object to be moved by the garbage collector if need be.
You when you add an instance of your UnitObject to two different collections, they both point to the same instance of UnitType.
And if you pass a reference type to a method, it is passed by reference: any changes made to the passed object by the called function persist once control returns to the caller.
Value types, are passed by value, näturlich, so adding something like an int to a collection means the collection receives a copy of the value. Ditto for passing value types to method: the method receive a copy of the value.
I have a question about they way C# functions, or methods, handle memory when certain objects are used as input arguments. I have tried searching for an answer to this but haven't been able to find anything, I might not know what to look for though.
The question: Say I have a really big integer array of size 10.000 by 10.000, called 'MyArray'. Lets say I moreover have some method called 'MyMethod' which takes several entries from two specified rows (this is the input) from MyArray and performs some operations on it, such as adding or multiplying these numbers, and then returns another integer.
To keep my code as short as possible I would prefer to make a method
MyMethod(int i, int j, int[][] MyArray)
rather than having to enter all the numbers from the array as seperate arguments. However does this mean the method creates a copy of MyArray when it is called or does C# know that if this data is only read and not edited in any way, that making a copy isn't needed?
In C#, arrays are actually objects, and not just addressable regions of contiguous memory as in C and C++. Thus, in our case, only the reference of the array is passed as an argument for the method.
C# does not create a copy as the array will be passed as a reference (like a C++ pointer) to the method. In general only struct types will be passed as a copy and normal class instances will be passed as a reference.
You can read more on the topic on MSDN
As you can read here : MSDN - Passing arrays as argument
Arrays can be passed as arguments to method parameters. Because arrays are reference types, the method can change the value of the elements.
Arrays are classes, and that's why they're just references and when we pass array into a method all we need is to pass an address (4 or 8 bytes). Proof:
Boolean isClass = typeof(int[][]).IsClass; // <- return true
Structs are passed by value, e.g. int is a struct:
Boolean isClass = typeof(int).IsClass; // <- return false;
English is not my mother tongue, exactly I am a Chinese. I'll be sorry if I cannot express my idea clearly.
I used to programme with c++. I really dont's understand the reference of C#.Many people tell me
the reference is similar to the pointer in c++.Such as below
Person Foo = new Person(); // C#
Person *Foo = new Person(); // C++.
Many times it works well.While many C# coders also tell me that the instance of class is just
the Foo.Foo has name.whiched is called Foo.name.Foo has age,which is called Foo.age. It seems the
thought is more easy to be used to code.But this thought does not conform to Memory model .
Please tell me What the reference is in c#.a object,or more likely a pointer?Thx.
You will want to get familiar with the different between Reference Type and Value Type.
Example is below:
void Main()
{
Foo A = new Foo{Age = 16}; //A creates a space in memory for the data of Foo and points to that memory location
Foo B = A; //B just creates a variable and points to the memory location created by A
A.Bar();
B.Bar();
//Result
//Your Age is 16
//Your Age is 16
A.Age = 24;
A.Bar();
B.Bar();
//Result
//Your Age is 24
//Your Age is 24 <----- B is pointing to the same location as A and reflects the changes on call.
FooValueType E = new FooValueType{Age = 23};
FooValueType F = E;
E.Bar();
F.Bar();
//Result
//Your Age is 23
//Your Age is 23
E.Age = 56;
E.Bar();
F.Bar();
//Result
//Your Age is 56
//Your Age is 23
}
public class Foo //These object are by reference
{
public int Age { get; set; }
public void Bar()
{
Console.WriteLine("Your Age is {0}", Age);
}
}
public struct FooValueType //These object are by value
{
public int Age { get; set; }
public void Bar()
{
Console.WriteLine("Your Age is {0}", Age);
}
}
C# has garbage collection and by default, it does not support pointers. You can however, use pointers as outlined here http://msdn.microsoft.com/en-us/library/t2yzs44b(v=VS.80).aspx
With respect to the variable behaviors, there are two kinds of types in C#:
Value types.
Reference types.
Value type variables carry the actual object as their value. Assigning a value type variable assigned from another value type variable copies the whole object. In C++ terms, this is like using a variable of the class type (not a pointer to the class) like for example when you're making a stack allocated instance. C# however doesn't give you that choice, but restricts this behavior only to such types as structs.
Reference type variables carry a reference to the actual object as their value. A reference to the actual object will most probably at least in involve the memory address of the object (but the details are hidden from you). Assigning a reference type variable from another reference type variable copies the reference, not the object, so now the two variables point to the same object. In C++ terms, this is like having a pointer variable of the class. C# however defaults to this behavior for variables of such types as classes and interfaces (and there's no way to jump back to the other behavior, as far as I know). The major difference between C# references and C++ pointers is that C++ pointers support arithmetic, while C# references don't. This is one of the ways C# ensures what we call memory safety. (C# does offer pointers, but they are used rarely and a lot of the time they are useful in interoperability scenarios. It'll likely be a long time before you ever need to use a pointer in C#.)
In the end, you can think that the C# reference is close to the C++ pointer (but, as outlined above, there are differences because the languages behave differently and give you different degrees of control and protection).
In C# when you say Person Foo = new Person();
new Person() creates an object of the class Person by allocating memory in heap section
returns a reference to this object (i.e nothing but reference to memory allocated) of type Person.
While Foo catches this reference and with this reference you can access the objects properties i.e its methods and variables.
In C++,
It follows the same steps but in c++ you catch a reference to object in a pointer of type Person.
More specifically new internally calls operator new function to allocate a memory dynamically to create objects.
In the image shown below Person p (on stack) creates an reference to an object returned by new Person().
age and name are the member variables of the Object.So we can easily access them using p.name and p.age.
More to add about stack and heap memory allocation in both c# and c++
The reference Foo always gets a memory on stack
Where object i.e here new Person() gets memory on heap and in case of C# more specifically it gets memory on managed heap
Updates
When you say new Person() it internally allocates memory for the Object Of the type -person.This object is composed of Persons members like shown in image.
You then can do two thing
Either you catch this reference in variable of type Person
e.g Person p = new Person();
Here p is a reference to memory location of object.So I can easily access Objects member using p.
Just don't store the reference directly use it e.g new Person().age will give me Persons age.This is called an anonymous Object.
Have you googled that before asking? There are many top resources on the internet and also some nice e-books.
However, here´s the memory model used in C# (in Java and PHP nearly as well):
Every object is inherited from the class object. That means, that nearly everything is an object in C#.
You don´t need to use pointer anymore. There´s nearly no need in C# for it. When you create an object, you will get back an reference to the instance in the stack. You could also have many references to one single object in stack. The references are located in the heap. This is the default behaviour and you aren´t able to change it, unless you do native code.
There´s no need of deleting something. It will be automatically happened by the Garbage Collector. It will be delete every local variable which is created inside a method at the end of it. The Garbage Collector will also delete objects, which got no reference anymore.
Internal datatypes are always located at the stack, strings also. For strings, they made an exception here, strings are also treated as simple datatypes, not as an object.
Every internal datatype will be copied per default, if you e. g. have give an int value to a method. This pattern is called "Call-By-Value". Every object will be passed by a new reference. That means, if you give an object as a method paremter, you will just get inside the method a new reference to the object. This pattern is called "Call-By-Reference". It´s very important, that you might divide in them.
You can change Call-By-Value to Call-By-Reference using the "ref" keyword. You could also define only an out parameter. That means, that doesn´t matter what value you give to a method. It will only return something at the end of the method. This can be done by using the "out" keyword in C#.
In logical conclusion to this, you are not able to overflow the heap in C#. Because the stack would get an overflow before...
There´s no difference anymore between static and object-calls. It´s always the dot. So, you could call public members of a class in the same way you would also call public static members of the class. For static members, you just need to use the class name, or inside the class without any keyword before the variable name. You call object/class member by using a reference to it.
You could only inherit from one class. Multiple inheritance is not supported it C# (Java and PHP as well).
Stdout commands (>> and >) changes to "Console" or to any other stream reference, e. g. file output streams.
Edit:
A child class inherits everything from the base class, also private and protected members/methods. But you can only access public and protected members/methods, unless you dont´ make use of reflections.
Hope, this helps you in order to unterstand C# a bit more...
The reference is a pointer to an object.
You can use "real" pointers in C# in unsafe code: here is an example
I am reading up on c# arrays so my question is initially on arrays.
What does declaring an array actually mean? I know you declare a variable of type array. When I have the following, what is actually happening?
int[] values;
Is it in memory by the time it is declared? If not then where is it? Is the array actually created here?
Then I go and instantiate an the array and initialise it with some values like:
int[] values = new int[] { 1, 2, 3 };
Does this actually go and create the array now? I have read that arrays are created when they are declared, others say that arrays are created when they are instantiated. I am trying to get my terminology right.
The same goes for an integer variable. If I have:
int value;
and
int value = 1;
When is int created? When is it added to memory?
Sorry for the dumb questions. I understand the concept but would like to know the technicallity behind the scenes of arrays.
What does declaring an array actually mean?
You didn't actually declare an array, you declared an array reference. Big deal in .NET, the difference between reference types and value types is important. Just having the array reference variable isn't enough, an extra step is required to create the array object. Which requires the new keyword. Which physically allocates the storage for the array object in the place where reference type objects are stored, the garbage collected heap.
The same goes for an integer variable
No, big difference. That's a value type. If it isn't a field of a class, not that clear from your question, then it is a local variable of a method. It gets created when the method starts running and poofs out of existence when the method returns. Very highly optimized, the core reason that value types exist in C#. The physical storage location is typically a cpu register or a slot on the stack frame if the method uses too many local variables.
If it is actually a member of a class then it gets created when the class object gets created. Just like an array, on the GC heap with the new keyword.
When you declare it like this:
int[] values;
you don't specify the size, so there is no way to know how much memory would be needed for an instatiation. This information is only given in the following line:
values = new int[] { 1, 2, 3 };
The memory requirements are deduced from the number of instatiation values (and from the memory requirements of the type int, of course).
When you declare an int like this:
int value;
the memory requirements are known and cannot change (since int is a value type). This variable can (and will) be created immediately. If you don't specify an initial value, it will have it's default value, which for int is 0.
int[] values;
Means that you declare a variable of type int[]. No memory is occupied yet, only a reference is created. The code above is initialized to a null-reference.
int[] values = new int[] { 1, 2, 3 };
This code declares a variable of type int[], and immediately creates an array. The variable references the newly created array.
Integers work a little different since they are value-types. Value types are initialized to their default values, in case of integers, the value 0.
If you split the declaration and the initialization, the following happens.
// This declares a variable
int[] values;
// This creates the array, and initializes the variable with the newly created array.
values = new int[] { 1, 2, 3 };
When you declare an array, internally all that is being created is a null pointer that is of type int[]. When you use the new keyword as in your example, or you use new int[6], at that time the system allocates memory for the size of the array.
Declaring an int will actually create the memory for the integer with default value of 0.
I have in my program a struct type called Square which is used to represent the location (int Rank, int File) of a square on a chess board.
If I assign Square by new Square sq(); say and then I want to reassign it, is it better to do so by
sq = new Square(rank, file);
or by writing an internal Set method and calling Set thus
sq.Set(rank, file);
What I am asking is when you use new on a struct, does the runtime reallocate new memory and call the constructor or does it reuse the existing memory? If it does the former then it would be better to write a Set method to avoid overheads would it not? Cheers.
The traditional thinking these days is the value types should be immutable, so you would not want to have a Set method unless that is returning a new Square object and not mutating the original. As such,
sq = new Square(rank, file);
And
sq = sq.GenerateSquare(rank, file); // renamed Set method from original question to appease comments
Should ultimately perform the same operation.
But given this approach, GenerateSquare would also possibly be better as a static method of Square rather than something depending upon any given instance. (An instance method would be more useful if something about the existing instance was used in the creation of a new instance.)
Structures are value types, so a simple assignment will do the job:
Square sq = new Square(rank, file);
Square anotherSq = sq;
Worrying about the weight of garbage collection or memory use is something you should not be concerned with until you have profiled your application and know it will be an issue. A simple structure like this is not going be taking up much space and likely not the cause of problems if your program does hit a bottleneck.
For structs... space for new structs is created on the stack, (see NOTE), not the heap, and is not subject to garbage collection. If the assignment variable is an already existing copy of the struct, then it is overwritten. No additional memory is used.
NOTE: If you create a new struct and assign it to a variable that is a property of a reference type, then yes, the reference type is on the heap, but the memory slot the struct is copied to is the already existing memory slot for that already existing reference type, no new heap memory is allocated. And the struct is not independantly subject to garbage collection....
But others' comments about your design are correct, structs should generally only be used for immutable domain objects, things that are simple and easy to create (small footprint) and have no identity (i.e., one telephone number object set to (802) 123-4567 is equivilent to and can be used anywhere else you need a telephone number object set to (802) 123-4567
So in general, these objects should not have constrcutors or property setters, they should have static factory methods that create instances of them.