Beginner question OOP: What is wrong with this increment on object array - c#

I am just starting out with OOP and trying to understand the code below. Why is book2 object changing its value even though i am not defining it to something els just using that object to define the values of the objects in books array.
Book[] books = new Book[5];
Book book2 = new Book("test", "test1", 800);
for (int i = 0; i < books.Length; i++)
{
books[i] = book2;
Console.WriteLine(books[i].pages);
books[i].pages += 10;
}
Is there something fundemental i have missed about objects? In my thinking this code should return 800, 5 times.
Just and explination how my thinking is flawed

You are assigning the same object reference to all positions in the array. So the Page += 10 that you are doing is being done always on the same object.
That is why you see 800, 810, 820 etc.

In C# there are two types of objects in terms of memory representation, with the terms "value type" and "reference type".
Value types hold their value by instance, and this type is underlying most simple types (integral numeric types, floating-point numeric types, bool and char)
Reference types are (simplified) "anything else". Precisely said, definied by using any of these keywords: class, interface, delegate, record, dynamic. Also the build-in types object, dynamic and string are reference types.
The reason for this difference can be abbreviated by performance. While it is quite efficient to store the data bits of number, for complex objects instead a reference is used, which can be thought of as the "number of the memory register" used to store the main data. This "register number" can be handled quite effiently.
As you defined class Book {...}, you created a reference type variable. Your for-loop is assigning each books[] item the "value" book2, they all are initialized to point to the same piece of memory. Thus modifying one of these instances will in turn modify modify all of them.
If you need independent instances, then you have assign a value including the new keyword, like fabian showed earlier. Eventually you will find that having a "copy constructor" can be quite handy (like in var anotherBook = new Book(existingBook);)

Related

Iterating through an object array; foreach(var... vs. foreach(object

object[] objArray = new object[]{"blah", 4, "whatever"};
foreach(var value in objArray) vs. foreach(object value in objArray)
I'm curious as to what the difference is between those, other than var must remain its type after assigned. Is one better than the other? Thanks.
From a purely functional perspective, var is just a shortcut for object here, since objArray's elements are of declared type object.
Using object is a sign to whoever's reading the code that the items in the array are not known to be any type more specific than object. The use of var does not connote this. In the minimal case you posted, it really doesn't make any difference to the clarity of the program which one you use.
If, on the other hand, it is not immediately clear from the context what type of object you are working with, then it may be advantageous to explicitly declare the type. On the other hand, if the type of the elements of the collection you're iterating over is verbose and obtrusive, then it may be advantageous to use var, so that the reader's eyes will be drawn to the logic of the code rather than a mess of generic parameters.
The only difference between var and any other type is that you let the compiler determine the type.
there is no difference between those two, var would be object in this case.
In your example no. But,
When declaring objects you get:
Boxing and Unboxing
However. When using var, it is compiled exactly as if you specified the exact type name.
So var tempval = 5; is the same as int tempval = 5;

How do I use parameters and return in C#?

For the life of me, every tutorial I look through, every video I've seen, every book I've read, I just can not understand how these things work exactly.
I see passing Values by Value, Value by Reference, Reference by Value, Reference by Reference. Can someone help me understand these with the most basic examples?
Same question in regards to return types. How do they work?
The best resource you will find on this is Parameter passing in C# by Jon Skeet. It gives a very clear explanation. If after reading that you still have questions, you should try to ask them more specifically so it is easier to help you.
First of all , you only see passing by value , or passing by reference. Not anything else.
Now to understand this concept, imagine you have a set of digital boxes marked 1,2,3, 4 etc. These boxes contain some data.
Then imagine you have a list of paper that states the same thing, i.e an index with 1,2,3,4.
Now you want to pass one of the contents(data) of the boxes to your friend.
You can do it in one of these two ways.
Passing by Value
Your friend checks your box, and copies it in his box/harddrive whatever. Assume your friend needs to change this data. If he does so, your original box is not affected because he changes the data that is in his box.
Passing by Reference
You just give the address of the box to your friend, and your friend will USE YOUR BOX instead of copying it. If he modifies the data, it will be from your box, your original data will be changed.
Before you understand return types, you have to understand data types. Begin there.
Let's back up a bit and start with variables.
Variables always contain some specific information. For value types, the information contained is the entire value directly. For reference types, the information contained is only a reference to some other memory location where the real value lives.
In .Net, you can pretend that variables are only really passed to or returned from functions in one way: by value. Forget passing by reference for now — it will just confuse things. When you pass a variable by value, the entire information directly held by the variable is copied to the function. The trick is understanding what this means for reference types, and that is simply that a copy of the reference is taken.
I can demonstrate with a simple code sample:
void Test(int x, dynamic y)
{
x = 3;
y.a = "four";
y.b = "five";
y = new {a = "six", b = "seven"}; // this will have no effect outside the function
}
int x = 2; // value type
var y = new {a = "one", b="two"}; //reference type
// both x and y are passed by value, but y is a reference type so the reference itself is copied
Test(x, y);
Console.WriteLine(x); //writes 2, because the test function is working with a copy
Console.WriteLine(y.a); //writes four
Console.WriteLine(y.b); //writes five
In the case of reference types, you can force a true "pass by reference", but you should never do this unless you really know what's going on. That would look something like this:
void Test(ref dynamic y)
{
y = new {a = "three", b="four"};
}
var y = new {a = "one", b="two"};
Test(y);
Console.WriteLine(y.a); //prints one
Console.WriteLine(y.b); //prints two
The output is still "one" and "two" because the function replaced the reference for the local variable. The code that called the function still has the reference to the original memory location, and so outputs the original value.

In C#, how do inferred variables using var behave with respect to memory and lifecycle?

Ok, I've been reading everything I can find on var, and I'm pretty sure I've got a handle on their basic behaviors and type inference. I've always been a big proponent of explicit types, so var makes me a little edgy when I'm reading code. So I have a couple of questions regarding its memory usage and the behavior of a variable declared with var over the course of that variable's lifecycle in memory.
Since var is an inference to an explicit or anonymous type, will its memory be allocated in the same place its corresponding type would be or is var universally created on the heap and accessed as if it were an object. As an example:
int i = 5; // puts this on the stack
var i = 5; // does this also go on the stack?
Does a declared var have a constant type once it is initialized or can it be adjusted as well? I ask this because I can't find in the documentation that specifies this, and I just read something in this SO question by #Eric Lippert:
a variable is a storage location whose
contents change
Having tested the following code, I see an implicit conversion exception even at the IDE level. I don't have the experience with LINQ at this point to run a similar test with respect to anonymous types. Do they follow this same behavior? Will the IDE recognize a type mismatch at design time or would such code receive a run-time exception?
var i = 5; // Initializes as int, value is 5
i = "Steve"; // Type casting error
Finally, is there ever a situation that you can think of where you may know a type at design time but it would be prudent to use var anyway? I ask because I've seen code samples where people do this, and from what I've read it strikes me as just lazy-coding.
EDIT: I realize there are a lot of articles talking about this topic, but I haven't found any that answer these questions specifically (though some hint one way or another). I would be happy to read any document you feel is relevant to these topics, just please post a link.
var is 100% syntactic sugar in the C# compiler. When the actual IL is generated, the type is explicitly defined. var-declared variables do not behave any differently from their explicitly-defined counterparts. The dearth of information you're seeing is coming from the fact that var is simpler than you're assuming. There is quite literally no difference between these two lines:
var i = 10;
int j = 10;
(Other than the fact that you see the words var and int, of course; they are functionally completely identical).
var variables are infered by the compiler, they are really just syntactical sugar, there is no difference between:
var i =0;
and
int i = 0;
in the compiled code.
They were added for the purpose of allowing anonymous types, e.g.
var MyVar = new { prop1="A string", prop2=5};
Yes var varables recognise a type mismatch at compile time, the compiler dynamically creates a class for them when it compiles. e.g. the below would not compile:
var MyVar = new { prop1="A string", prop2=5};
MyVar = "Fred";
As others have said, var has no effect on how the variables behave in terms of memory - it just means you don't specify the name. For anonymous types you couldn't specify the name, first because you don't know it at compile time, and second because the names are deliberately "unspeakable" - they're not valid in C#. (Generally they contain <> for example.)
The IL generated for code using var and code using an explicit name is exactly the same. Just as a normal variable can't change type, nor can a variable declared using var... so in your example where you try to assign the value "Steve" to a variable which has an implicit type of int, you'll get a compile-time error exactly as if you'd explicitly declared it to be of type int.
As for when to use var and when not to, I have a few rules of thumb:
Obviously if you want the variable to have a type other than the compile-time type of the assigned expression, you've got to do it explicitly
For constructor calls, it's always clear what the the type is even if you're using var
var is useful for emphasizing what the code is meant to do rather than how
Often I use var if the explicit name would be extremely long - particularly for generics with multiple type arguments.
Basically it's all about readability: if the code is easier to read using var, go for it. If not, don't. Note that this isn't the same as saving typing... code is generally read more than it's written, so think about your reader. Eric Lippert wrote a great note when tech reviewing the first edition of C# in Depth, which is worth a read.
Simple answer: exactly the same as normal variables.
var declarations are translated into specific (strong) types at compile-timee. var is simply a method of automatic type inference, and has nothing to do with dynamic languages. At the end of the day, it's just the compiler being clever and translating var into what actual type you want.
"Since var is an inference to an explicit or anonymous type, will its memory be allocated in the same place its corresponding type would be or is var universally created on the heap and accessed as if it were an object"
The important thing about var, is that the compiler changes the var statement to the actual type at compile time, so:
var number = 1;
Will get changed to:
System.Int32 number = 1;
...by the compiler. And as such the memory locations for storage of these types is no different. var is essentially syntactic sugar. So, method local declarations of value types will get stored on the stack, reference pointers will get stored on the stack with the referenced objects on the heap.
Once you have declared a variable as var, because this is translated into its full type by the compiler, you can't then dynamically change the type:
var i = 5;
i = "Steve";
...is invalid, because its already been declared as an Int32.
Anonymous types follow a similar behaviour, where a type is created by the compiler during compilation.
"Finally, is there ever a situation that you can think of where you may know a type at design time but it would be prudent to use var anyway?"
Personally, I follow a simple pattern:
For primitives, I always put the type:
int i = 5;
string name = "Matt";
For complex types, I mostly do this:
var instance = new MyComplexTypeInstance();
For LINQ results, I stick to var:
var result = from i in something select i;
For methods, if the method is descriptive of the type being returned, then I will use var.
var instance = GetInstance();
Whereas, more complex method names, I'd put the actual type:
Result result = DoSomethingWeirdAndWonderful();
Each developer will find something they are comfortable with, the choice is yours. As var is only really a design-time thing, its all syntactic sugar.

Which is a lighter object

I am confused here. Which is lighter object? is orgWithNullImageCollection or orgWithImageCollection ? in the below code. Or is it lighter object concept at all. Please find the code snippet below for the reference.
class Orgnization
{
public Collection ImageCollection { get; set; }
}
Organization orgWithNullImageCollection = new Organization();
org.ImageCollection = null;
Collection imageCollection = new Collection();
// Adding 100 images to imageCollection
Organization orgWithImageCollection = new Organization();
org.ImageCollection = imageCollection;
Is there any difference in performance if I pass these two objects to any other methods? ie passing orgWithNullImageCollection over orgWithImageCollection ?
I believe that, it won't make any difference whether ImageCollection property of Organization objects points to something or not.
Please clarify.
You never pass objects in C# - only ever values of value types, or references. In this case, you'd be passing a reference as you're dealing with a class. The reference will be the same size (4 or 8 bytes) regardless of the contents of the object it refers to (if any).
In this case, both objects will be the same size - it's just that one of them will have a null reference where the other has a reference to a collection.
As such you could regard the one with the collection as "heavier" in that are two objects involved instead of one. The extra collection will take memory, obviously - whereas a null reference doesn't refer to any object, so only the size of the null reference itself is required.
For more information, see my article about value types and reference types and argument passing.

Chaining properties in C# & unexpected results

I was just having a quick read through this article (specifically the bit about why he chose to use structs / fields instead of classes / properties) and saw this line:
The result of a property is not a true l-value so we cannot do something like Vertex.Normal.dx = 0. The chaining of properties gives very unexpected results.
What sort of unexpected results is he talking about?
I would add to dbemerlin's answer that the key here is Rico's note that properties are not "lvalues", or, as we call them in C#, "variables".
In order to mutate a mutable struct (and ideally, you should not; mutable structs often cause more problems than they solve) you need to mutate a variable. That's what a variable is -- a storage location whose contents change. If you have a field of type vector and you say
Foo.vector.x = 123;
then we have a variable of value type -- the field Foo.vector -- and we can therefore mutate its property x. But if you have a property of value type:
Foo.Vector.x = 123;
the property is not a variable. This is equivalent to
Vector v = Foo.Vector;
v.x = 123;
which mutates the temporary variable v, not whatever storage location is backing the property.
The whole problem goes away if you abandon mutable value types. To change x, make a new vector with the new values and replace the whole thing:
Foo.Vector = new Vector(x, Foo.Vector.y);
The only "unexpected" result would be that the assignment wouldn't last because Vertex.Normal returns a copy and the code assigns 0 to dx of the copy.
I can't test it now but that is what i would expect (from what i know of .NETs handling of structs)

Categories

Resources