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.
Related
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);)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
To give context to the code imagine a collection of objects inside a cube. The objects are placed randomly and can affect each other. Several series of test events are planned then executed against the cube of objects. Only the best result is kept. This is not the real problem but a simplified version to focus the question.
Sample code
class Loc{
double UpDown
double LeftRight
double FrontBack
}
class Affects{
string affectKey
List<string> impacts //scripts that execute against properties
}
class Item{
Loc startLoc
Loc endLoc
List<string> affectedBy
string resultText // summary of analysis of changes
}
class ItemColl{
List<Item> myItems
}
class main{
ItemColl items
List<string> actions
void ProcessAffects(ItemColl tgt, List<string> acts){
// take actions against the tgt set and return
}
int IsBetter(ItemColl orig, List<Items> altered){
// compares the collection to determine "better one"
// positive better, negative worse, zero for no change
}
void DoThings(){
// original code
ItemColl temp = items
ProcessAffects(temp,actions)
IsBetter(temp,actions)
// the result was always zero - admittedly a duh error
}
}
When I added an alternate constructor that copied the object passed in and did the same to all subordinate objects, as in
class ItemColl{
public ItemColl(){}
public ItemColl (ItemColl clone){
// do a deep copy
}
// partial code from main DoThings
// replaced ItemColl temp = items
// with
ItemColl temp = new ItemColl(items)
it solved the problem that lead me to first question. (Thanks to the people who answered that question kindly.) What I am stuck on is whether or not there are other options to consider? I am hoping this restatement has a better focus and if I am not taking advantage of some newer efficiencies I would like to know.
I removed the old question entirely and re-phrased post face-palm.
Before you get into parameters, you need some background:
Background
There are two kinds of objects in .NET-land, Reference types and Value types. The main difference between the two is how assignment works.
Value Types
When you assign a value type instance to a variable, the value is copied to the variable. The basic numeric types (int, float, double, etc) are all value types. As a result, in this code:
decimal dec1 = 5.44m;
decimal dec2 = dec1;
dec1 = 3.1415m;
both decimal variables (dec and dec2) are wide enough to hold a decimal valued number. In each case, the value is copied. At the end, dec1 == 3.145m and dec2 == 5.44m.
Nearly all value types are declared as a struct (yes, if you get access to the .NET sources, int is a struct). Like all .NET types, they act when boxed as if they are derived from the object base class (their derivation is through System.ValueType. Both object (aka System.Object) and System.ValueType are reference types, even though the unboxed types that derive from System.ValueType are value types (a little magic happens here).
All value types are sealed/final - you can't sub-class them. You also can't create a default constructor for them - they come with a default constructor that initializes them to their default value. You can create additional constructors (which don't hide the built-in default constructor).
All enums are value types as well. They inherit from System.Enum but are value types and behave mostly like other value types.
In general, value types should be designed to be immutable; not all are.
Reference Types
Variables of reference types hold references, not values. That said, it sometimes help to think of them holding a value - it's just that that value is a reference to an object on the managed heap.
When you assign to a variable of reference type, you are assigning the reference. For example:
public class MyType {
public int TheValue { get; set; }
// more properties, fields, methods...
}
MyType mt1 = new MyType() {TheValue = 5};
MyType mt2 = mt1;
mt1.TheValue = 42;
Here, the mt1 and mt2 variables both contain references to the same object. When that object is mutated in the final line of code, you end up with two variables both referring to an object whose TheValue property is 42.
All types declared as a class are reference types. In general, other than the numeric types, enums and bools, most (but not all) of the types that you normally encounter will be reference types.
Anything declared to be a delegate or an event are also reference types under the covers. Someone mentioned interface. There is no such thing as an object typed purely as an interface. Both structs and classes may be declared to implement an interface - it doesn't change their value/reference type nature, but a struct stored as an interface will be boxed.
Difference in Constructor Behavior
One other difference between Reference and Value Types is what the new keyword means when constructing a new object. Consider this class and this struct:
public class CPoint {
public float X { get; set; }
public float Y { get; set; }
public CPoint (float x, float y) {
X = x;
Y = y;
}
}
public struct SPoint {
public float X { get; set; }
public float Y { get; set; }
public CPoint (float x, float y) {
X = x;
Y = y;
}
}
They are basically the same, except that CPoint is a class (a reference type) and SPoint is a struct (a value type).
When you create an instance of SPoint using the two float constructor (remember, it gets a default constructor auto-magically), like this:
var sp = new SPoint (42.0, 3.14);
What happens is that the constructor runs and creates a value. That value is then copied into the sp variable (which is of type SPoint and large enough to hold a two-float SPoint).
If I do this:
var cp = new CPoint (42.0, 3.14);
Something very different happens. First, memory is allocated on the managed heap large enough to hold a CPoint (i.e., enough to hold two floats plus the overhead of the object being a reference type). Then the two-float constructor runs (and that constructor is the only constructor - there is no default constructor (the additional, programmer-written constructor hides the compiler generated default constructor)). The constructor initializes that newCPoint in the memory allocated on the managed heap. Finally, a reference to that newly create object is created and copied to the variable cp.
Parameter Passing
Sorry the preamble took so long.
Unless otherwise specified, all parameters to functions/methods are passed by value. But, don't forget that the value of a variable of reference type is a reference.
So, if I have a function declared as (MyType is the class declared above):
public void MyFunction(decimal decValue, MyType myObject) {
// some code goes here
}
and some code that looks like:
decimal dec1 = 5.44m;
MyType mt1 = new MyType() {TheValue = 5};
MyFunction (dec1, mt1);
What happens is that the value of dec1 is copied to the function parameter (decValue) and available for use within MyFunction. If someone changes the value of the decValue within the function, no side effects outside the function occurs.
Similarly, but differently, the value of mt1 is copied to the method parameter myObject. However, that value is reference to a MyType object residing on the managed heap. If, within the method, some code mutates that object (say: myObject.TheValue=666;), then the object to which both the mt1 and myObject variables refer is mutated, and that results in a side effect viewable outside of the function. That said, everything is still being passed by value.
Passing Parameters by Reference
You can pass parameters by reference in two ways, using either the out or ref keywords. An out parameter does not need to be initialized before the function call (while a ref parameter must be). Within the function, an out parameter must be initialized before the function returns - ref parameters may be initialized, but they do not need to be. The idea is that ref parameters expect to pass in and out of the function (by reference). But out parameters are designed simply as a way to pass something out of the function (by reference).
If I declare a function like:
public void MyByRefFunction(out decimal decValue, ref MyType myObject) {
decValue = 25.624; //decValue must be intialized - it's an out parameter
myObject = new MyType (){TheValue = myObject.TheValue + 2};
}
and then I call it this way
decimal dec1; //note that it's not initalized
MyType mt1 = new MyType() {TheValue = 5};
MyType mt2 = mt1;
MyByRefFunction (out dec1, ref mt1);
After that call, dec1 will contain the value 25.624; that value was passed out of the function by reference.
Passing reference type variables by reference is more interesting. After the function call, mt1 will no longer refer to the object created with TheValue equal to 5, it will refer to the newly created object with TheValue equal to 5 + 2 (the object created within the function). Now, mt1 and mt2 will refer to different object with different TheValue property values.
With reference types, when you pass a variable normally, the object you pass it may mutate (and that mutation is visible after the function returns). If you pass a reference by reference, the reference itself may mutate, and the value of the reference may be different after the function returns.
All custom objects (derived from tobject) are "Reference type".
Nope. See the docs pages for Reference Types and Value Types
The following keywords are used to declare reference types:
class
interface
delegate
C# also provides the following built-in reference types:
dynamic
object
string
A value type can be one of the two following kinds:
a structure type ...
an enumeration type ...
So any time you make a class, it's always a Reference type.
EVERY type inherits from Object - Value Types and Reference Types.
Even if you pass it to a function with a reference parameter, as with the RefChange function both items are changed and both have exactly the same values in the integer list.
The ref keyword just forces your parameter to be passed by reference. Using ref with a Reference Type allows you to reassign the original passed in reference. See What is the use of “ref” for reference-type variables in C#?
.
Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same. A method parameter can be modified by ref regardless of whether it is a value type or a reference type. There is no boxing of a value type when it is passed by reference.
Source
Of course, the ref keyword is important when you pass in a Value Type, such as a struct.
If you want to pass a copy of an object, create an overloaded constructor to which you pass the original object and inside the constructor manage the duplication of the values that matter.
That's called a Copy Constructor, and is a long-established pattern, if you want to use it. In fact, there is a new c# 9.0 feature all about it: records.
well i cant comment since my reputation is too low, but value types are usually in built types such as int, float ...
everything else is reference type. reference type is always a shallow copy regardless of ref keyword.
ref keyword mainly served for value-type or act as a safeguard.
if u want to deep copy, Icloneable is very useful.
I have two objects say Object1,Object2.
The two objects have the same properties.
My code is like below
Object1.property1=Object2.property1; // Object2.property1=**x**
Object2.property1= **y**;
When I try to retrieve the Object1.property1 it is displaying y.
Here I Don't want to change the Object1.property1 but it is Getting Modified when Object2.property1 has changed.
My Questions is
Why my code is behaving like that or Is there any concept that i don't know in c# ?
It is behaving like that because you don't actually have 2 objects. You only have one.
Object1 and Object2 are simply variables. They are not objects themselves. They store a "reference" that points to the object. You can use the variables to access the object. In some point in your code, you most probably have written
Object1 = Object2;
or
Object2 = Object1;
This makes the two variables hold 2 references that refers to the same object. When you edit the object by accessing through the variable Object1, you can see the effect by accessing the object through Object2. Because they are the same object.
Fore more details you read concept of : Deep Copy vs Shollow Copy
if you want to change that behavior than you need to make use of cloning/copy , right now you are assigning reference and that's why its changing in both the object ,
as property is byte array then you can do like this ,Array.CopyTo Method (Array, Int32)
Array1.CopyTo(Array2, 0);//
so in your case its like
Object2.property1.CopyTo(Object1.property1,0);
Object2.property1= **y**;
You might have to have a look at this Microsoft doc. The concept of value and reference types variables is a very basic and very important concept of c#.
Simply said: if you crate an object like this:
object2 = object1;
You dont really create a new object. You just reference the first object with the second one. If eiter of those gets edited both do at the same time since they are the same object after all.
Unfortunately there is no built in way to simply clone an object, but you coud create an overload to create a new object and pass the source object as argument tocopy all the attributes individually. if there are too many attributes you could also use reflection to procedurally copy all attributes defined in the object.
Just to understand what's gone under the hood for reference types and based on article from Eric Lippert http://blogs.msdn.com/b/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx I would like to understand in depth why this code is working like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
MyCalleeClass calleeClass = new MyCalleeClass();
calleeClass.MyTestProp = "toto";
MyCallerClass callerClass = new MyCallerClass();
callerClass.TestMethod(calleeClass);
//normally given that a class it's a reference type this should give a toto 1
Console.WriteLine(calleeClass.MyTestProp);
}
}
class MyCalleeClass
{
public string MyTestProp { get; set; }
}
class MyCallerClass
{
public void TestMethod(MyCalleeClass calleeClass)
{
Console.WriteLine("In the caller method");
//does this object is created on the stack or on the heap
calleeClass = new MyCalleeClass();
calleeClass.MyTestProp = "toto 1";
Console.WriteLine(calleeClass.MyTestProp);
}
}
}
another question if the caleeClass in the testMethod is not created on the stack is there a partiular case where a reference type could be created on the stack
The fact that something is an "implementation detail" means that the actual implementation is not something you should need to know.
So let's deal with the details first:
When you construct an object of a reference type, that object lives on the heap
The reference, however, can live a lot of places:
As a temporary element on the stack
As a variable on the stack
As a field of a value type (and not it lives wherever the value type lives)
As a field of a reference type (and since the reference type lives on the heap, the fields inside it does too)
But this question actually seems to confuse the following two concepts:
Passing a reference type parameter
Passing a parameter by reference
These are two different things, and in the case of your question, the correct statement would be that you're passing a reference type parameter by value.
This all starts to get confusing for a lot of people so let's try to look at what is happening here.
In reality, a reference is just a number. It's something that refers to an object somewhere else in memory. Most likely the number is the address (in memory) of that object.
So, after you've constructed the first object here:
MyCalleeClass calleeClass = new MyCalleeClass();
calleeClass.MyTestProp = "toto";
let's say that calleeClass contains the number (reference) 1234. At address 1234 there lives an object of type MyCalleeClass, and the MyTestProp property of that object has the value "toto".
Ok, then you pass this reference to that method. Basically, you give that method a copy of the reference 1234.
Inside that method you construct another object and assign the reference to this object to the same local variable (the parameter), overwriting the 1234 reference with, say, 5678. Pointing to your new object.
And now you change the property of that object, the new one.
Then you return back to the outer code. Since that code gave the method a copy of the reference 1234, its reference still has 1234 and points to the original object, with "toto" in the property.
This is what it means to pass a reference by value, you give the method a copy of the reference value. The code that is calling still has the original reference.
If you want the code that is calling to continue using the new reference you need to pass the reference by reference. This is also confusing because the two "reference" words here actually mean different things.
A reference is a reference to an object
Passing by reference means to pass access to the underlying variable, and not just a copy of its value
TL;DR Your code behaves the way it does because you're using one object on the outside, and construct and change a new object on the inside, but the outside world does not get back that new object and continues to use the old one.
As for your second question, can a reference type be allocated on the stack, then no. All objects are allocated on the managed heap.
You can allocate something which looks like a reference type on the stack, arrays of primitives/value types, in unsafe code, like this:
unsafe void Test()
{
int* values = stackalloc int[10];
}
But this isn't an "array reference type", it's just a pointer to the first of 10 int values allocated on the stack, so it's not the same thing.
This can turn into a large discussion.
In your TestMethod the MyCalleeClass is generated.
Since this is a class(ref. type) then it's generated on the heap(lets say at address 1000).
Your stack will contain a pointer to address 1000.
At address 1000 you will have another reference to the string you have in your class(a string is also a ref. type that will sit in address 2000 - for this example).
So:
TestMethod's stack will have a pointer to address 1000.
In address 1000 you will have a pointer to address 2000.
In address 2000 you will have a string.
In your main:
callerClass.TestMethod(calleeClass) -> the reference to the calleeClass is copied as an argument
in your TestMethod
calleeClass = new MyCalleeClass -> the copied reference (argument of the method) is overwritten to reference another object
when the TestMethod call is returned, the reference is not copied back, so you are still referencing the original class in your main.
If you do want the behaviour you suggest, you should specify: TestMethod(ref MyCalleeClass calleeClass).
Lets say I have a populated array of objects.
Resource[] list = new Resource[100000];
And once in a while, I would like to change an object in this list to a default value.
Resource defaultResource = new Resource();
And later on, I would like to check if the item is default or not.
So, I am wondering what the performance differences might be in setting the list object to a default value, versus setting a value to null.
list[i] = defaultResource; /*versus*/ list[i] = null;
So really, I would like to know what goes on behind the scenes when a value is set to null versus setting it equal to something else.
Sorry if this is a dumb question!
There's not much difference between setting a variable to an existing object vs. setting it to null. In both cases, the object that has been referenced by that variable before would get one step closer to becoming eligible for garbage collection, regardless of the new value stored in that variable being a null or a different object. The rest of the assignment goes in the same way, too: CLR does not maintain reference count, so nothing special needs to happen specifically at the point when the assignment is made.
It may be beneficial to store a default object in place of a null to avoid extensive null checking at runtime, though: doing so simplifies the code, and reduces the need for branching at runtime.
One possible option to consider for your scenario - you want the simplification of not having to write null checking code.
Consider subclassing your Resource class with a stub that represents a default value.
public class NoResource : Resource { }
// ... later
if (res is NoResource) {
// handle default value
}
This way, your code is still able to work with Resource objects as it expects to be able to, and you can optionally check for a default Resource easily.