When I am updating my obj as null its output is 30 but no exception but when I am updating obj.Age = 25 output is 25.
I am not getting the idea what is happening behind the scene.
Can someone explain why this is happening?
public class A
{
public int age;
}
class Program
{
public static void Test(A obj)
{
//obj = null;
//obj.age = 25;
}
static void Main(string[] args)
{
try
{
A obj = new A();
obj.age = 30;
Test(obj);
Console.WriteLine(obj.age);
}
catch (Exception)
{
throw;
}
}
}
Notice the method signature -
public static void Test(A obj)
The parameter is not passed as ref. When the reference types are passed as parameter, without specifying as ref. You can change the properties values within the object, but you cannot assign the object to point it to another memory location.
In simple words you cannot do -
obj = null OR obj = new A() OR obj = instanceOfAnotherObject
To be able to even change the object, you need to change the method signature and pass obj by ref -
public static void Test(ref A obj)
When you do obj = null; then you do not set the object to null but the reference to that object to null. As in your method Test the parameter is a new reference to the passed object, it does not affect the obj reference in Main and so setting obj to null in Test has only an effect in that method.
To do / see what you want you may want to change the parameter of Test to a ref parameter like so
public static void Test(ref A obj)
and then call Test like so
...
A obj = new A();
obj.age = 30;
Test(ref obj);
...
as now you actually modify the obj reference of the Main method.
When you do obj.age = 25; in Test (of course without setting obj to null in front of it) then you modify the same object as obj in Main points to and so when writing the age to the console you will see 25.
That is possible because it was passed by reference - if you replace A with e.g. int and pass that around then changing its value in Test will not be reflected in the output of Main as integers are passed by value. You may find reading this page and the subsequent pages to it helpful
Related
Here is my scenario: I am trying to get a value from frontend using AJAX and then want to use this in a non-static method for some calculations. But I am getting an error:
Object reference not set to an instance of an object
I know how to use non-static method/data members in a static method by creating obrect Reference that I did but still error is same.
Code:
[WebMethod]
[WebScript]
public static string refAssignments(getVal rf)
{
string value = rf.valueFromAJAX;
MyClass obj = new MyClass();
string result = obj.analyse(value);
}
Here Analyse() is a non-static method all I want is to use this method inside the static method refAssignments.
I tried earlier questions but wasn't successful! Can someone point where I am doing wrong
The problem isn't relevant with the Analyse method is non-static or not. Probably, rf object is null. Check the rf object;
if (rf != null)
{
string value = rf.valueFromAJAX;
MyClass obj = new MyClass();
string result = obj.analyse(value);
}
else
{
//Do something
}
I can declare an Action and pass it a method on an instance object which modifies that object's internal state, then call the method and see that the private instance variables have changed. But if I create the Action, then null out the object it has a reference to a method on I don't get a null reference exception when I invoke the Action, but obviously I do if I try to access the object.
How can it be changing anything if there is nothing there to change?
A contrived example where I create a builder object which has a public void BuildWall method which just increments the number of walls it has built (a private integer variable). Why can I call buildWallAction after I have set builder to null or else how is the Action modifying the object if the object doesn't need to exist in order to call the action?
Thanks in advance :)
class Program
{
static void Main(string[] args)
{
Builder builder = new Builder("Jim");
Console.WriteLine(builder.ToString());
Action buildWallAction = builder.BuildWall;
builder = null; //no more builder to change via BuildWall()
//starts work
buildWallAction(); //these calls modify _wallsBuilt on the builder object
buildWallAction(); //but if we set it to null we can still call them just fine
Console.WriteLine(builder.GetBuildingStatus()); //we will only get an exception here if builder is null
Console.ReadKey();
}
}
public class Builder
{
private string _name;
private int _wallsBuilt;
public Builder(string name)
{
_name = name;
_wallsBuilt = 0;
}
public void BuildWall()
{
_wallsBuilt++;
}
public string GetBuildingStatus()
{
string msg = $"{_name} has built {_wallsBuilt} walls.";
return msg;
}
}
Your builder variable isn't the instance, it is a reference to the instance. So setting the variable to null, doesn't 'erase' the instance, you only get rid of the reference so you cannot access it anymore.
The buildWallAction variable is a reference to the method BuildWall of the instance. This is no way directly related to the builder variable. Setting the builder variable to null doesn't do anything to the buildWallAction variable.
I tried with the below code, I got the output as 1000. I heard assigning object must share the reference instead of copying the entire object memory. Here the result is different.Can anyone help.
public aaaaa ad = new aaaaa();
static void Main(string[] args)
{
Program p = new Program();
p.fun1();
p.fun2();
}
public void fun1()
{
using(smallclass s = new smallclass())
{
s.j = 1000;
ad.fun1(s);
}
}
public void fun2()
{
ad.fun2();
}
public class aaaaa
{
public smallclass h = new smallclass();
public void fun1(smallclass d)
{
h = d;
}
public void fun2()
{
Console.WriteLine(h.j);
}
}
public class smallclass:IDisposable
{
public int j = 9;
public void Dispose()
{
GC.SuppressFinalize(this);
}
}
Update:
I expect an object reference exception as the referenced memory is disposed in p.fun1();
Here is an simple example how assinging works
using System;
namespace ConsoleApplication1
{
internal class Program
{
private static smallclass objA = new smallclass();
private static smallclass objB = new smallclass();
private static void Main(string[] args)
{
showValues();
objA.value = 1000;
showValues();
objB = objA;
showValues();
objA.value = 1055;
showValues();
}
private static void showValues()
{
Console.WriteLine("objA.value: " + objA.value);
Console.WriteLine("objB.value: " + objB.value);
Console.ReadLine();
}
}
internal class smallclass : IDisposable
{
public int value = 0;
public void Dispose()
{
//Here you can remove eventHandlers
//or do some other stuff before the GC will play with it
}
}
}
Like you can see
first we create 2 objects objA and objB
than we show the values like expected they are both 0
after that we increase the value of objA to 1000
the value of objA a is 1000 and the value of objB remains at 0
NOW we assingning objA and objB
so the value of objB got also 1000
if we now change the value of objA to 1055
the value of objB get also changed
because objB is no more an separate object it now holds the same
reference like objA does
EDIT
And now i will show you how you get your Error based on your example
change your aaaaa class to:
public class aaaaa
{
public WeakReference<smallclass> h;
public void fun1(smallclass d)
{
h = new WeakReference<smallclass>(d);
}
public void fun2()
{
smallclass k;
if(h.TryGetTarget(out k))
Console.WriteLine(k.j);
else
Console.WriteLine("ERROR ERRROR ERROR");
}
}
and modify your static void Main(string[] args) to:
static void Main(string[] args)
{
Program p = new Program();
p.fun1();
GC.Collect();
p.fun2();
Console.Read();
}
Ok lets get through the changes
we are using the WeakReference<T> (you could also use WeakReference)
if the GC now comes across our object he can't find a StrongReference so can Collect it
now to the GC.Collect() YOU need to call it because it forced the GC to do his work (now at this moment)
and remember like i told you before IDisposable will get called from the GC before he destroys the object (AFAIK) so there is the place to put all the stuff that need to be done before the object will get destroyed
No, assingning is not a "new" statement, it copies.... a reference, it does not create a new object. For a class.
For a struct, it does so.
I suggest learning C# by reading the documentation or a book - those basics are normally handled to great detail in those.
You will not go far wrong if you think of every reference type variable, field, parameter, array slot, or other such storage location, has holding either "null", or "object #24601" [or some other number]. There are really only a handful things that can be done with references:
You may create a null reference
You may ask the system to create a new object and return a reference to it
You may copy one reference to another
You may check whether two references are equal to each other, or whether one is equal to null.
You may ask the system to perform some action upon the object identified by a reference
If myCar is a variable of some reference type, a statement like myCar.Color = CarColors.Blue won't affect the variable myCar at all. Instead, it will observe that myCar holds [e.g.] "Object #8675309", and then ask the system to access the Color property or field of object #8675309. Conversely, if otherCar happens to hold "object #90210", a statement of the form otherCar=myCar won't do anything with object #8675309, nor object #90210, but will instead replace the "90210" stored in otherCar with "8675309".
Objects are guaranteed to exist as long as any form of reference to them exists, but if there are two objects which, although referenced by each other, are not referenced by anything else in the universe, both objects may simultaneously cease to exist. This rule is absolute, but there are a couple of twists: code may request a WeakReference to an object; an object is guaranteed to exist as long as a weak reference to it exists, but if the system discovers that no strong references to an object exist, it will invalidate every WeakReference to it. Further, the system keeps a list of all objects that have would like to be notified if they are abandoned. If the system finds that this list holds the only reference to an object, it will move the object to a strongly-referenced list of objects whose Finalize method should run at the first convenient opportunity. When the object's Finalize method is run, the reference will be removed from that latter list. If no reference to the object has been stored anywhere in the mean time, the object will cease to exist.
I have replaced GC.SuppressFinalize with GC.Collect() in dispose function, however this is not freeing the memory.. and am receiving 1000 as a result.
I guess, as it holds other reference(the variable h), GC will not free the memory, even if we invoked it explicit.
So we can very well pass and assign the objects irrespective of the allocated(new) object going out of scope.
Please correct me If i am wrong.
I am having a hard time understanding this.
If we pass variable by reference the method we are calling can change the value of the Caller's variable by changing its paramater value .
My question is
we have two variables
int _myinteger=10;
object _myobject=null;
here _myinteger is a value type and _myobject is reference type variable ,I want to know how can we pass these variable's by reference and how does it change's the value.? can anyone explain with an simple example.
Thank you all
You can pass the int by reference with the ref command, and the object is already passed by reference. More specifically, the reference to the object is passed by value.
In other words, value types are by default passed by value and reference types are by default passing their reference by value.
Consider this code:
public void ByRef(ref int i, object o)
both there are passed by reference.
UPDATE: the community wants to clarify this statement. If you were to change a value on the object that is passed it would be changed at the caller. However, if you were to build a new one (e.g. o = new Object();) with the aforementioned signature the caller would not change. If you wanted that to work as well you'd need to do this:
public void ByRef(ref int i, ref object o)
Use ref keyword, It helps you to pass value by reference.
The ref keyword causes an argument to be passed by reference, not by
value. The effect of passing by reference is that any change to the
parameter in the method is reflected in the underlying argument
variable in the calling method. The value of a reference parameter is
always the same as the value of the underlying argument variable.
private void DoSomething(ref int someintByRef)
{
someintByRef = 4;
}
int _myinteger=10;
DoSomething(ref _myinteger);
Console.WriteLine(myinteger);//Prints 4
Update:
To be more clear, I'd say without the use of ref "value types" and "reference types" are passed by value only. Difference is for "value types" value(complete instance) will be copied and completely new instance is passed in case of reference types "refence of the instance" is copied and passed by value.
When we use ref, no doubt both are passed by reference
For reference types:
class User
{
public string Name { get; set; }
public string LastName { get; set; }
}
void ByRef(ref User user)
{
user = new User();
}
void ByVal(User user)
{
user = new User();
}
void Test()
{
var user = null;
ByVal(user);
// user is still null
ByRef(ref user);
// user is new User()
}
There are diffrent behavior for the diffrent type of variables. if we talk about value types they are consist about the values only. the don't share memory locations. so every value type have there own values and they can play with it as they want. on the other hand refrence type variables are diffrent in nature they work with sharing mode so if i create an object then the value of this object is being shared by their users. I recomand you to have a look for below video for more clearification.
So if you pass a value type variable to a method the copy of values is being assigned to the using variable. so if you want to use the same variable. then you can have ref keywork for refranceing the value of the same object. on the other side object / refrence type variables are not needed to be ref keyword as they are already refranced by default nature.
Try below code tu understand the behavior.
class Program
{
static object reftypedata = "I am Testing. ";
static int valuetypeData = 10;
static void Main(string[] args)
{
CalcValue(valuetypeData);
CalcValuewithRef(ref valuetypeData);
Calcobject(reftypedata);
Console.ReadKey();
}
public static void CalcValue(int i)
{
Console.WriteLine("Value Type.....");
Console.WriteLine("before Processing i={0}", i);
i = 100;
Console.WriteLine("After Processing i={0}", i);
Console.WriteLine("After Processing valueTypeData = {0}", valuetypeData);
}
public static void CalcValuewithRef(ref int i)
{
Console.WriteLine("Value with Ref Type.....");
Console.WriteLine("before Processing i={0}", i);
i = 100;
Console.WriteLine("After Processing i={0}", i);
Console.WriteLine("After Processing valueTypeData = {0}", valuetypeData);
}
public static void Calcobject(object value)
{
Console.WriteLine("Reference Type.....");
Console.WriteLine("before Processing value={0}", value);
value = "Default Value Has been Changed.";
Console.WriteLine("After Processing value={0}", value);
Console.WriteLine("After Processing reftypedata={0}", reftypedata);
}
}
Output:
Value Type.....
before Processing i=10
After Processing i=100
After Processing valueTypeData = 10
Value with Ref Type.....
before Processing i=10
After Processing i=100
After Processing valueTypeData = 100
Reference Type.....
before Processing value=I am Testing.
After Processing value=Default Value Has been Changed.
After Processing reftypedata=I am Testing.
you also can reffer to this youtube video.
I'm just curious how this works:
In my class Form1.cs I have declared an object static:
public static Class1 class1;
This is how the constructor of Class1 looks like:
public Class1()
{
Form1.class1 = null;
}
I expected to get a null reference exception in MS VS 2010
class1 = new Class1();
class1.showMSG();
But instead it just executes showMSG() (showMSG is not static) like I've never set the reference to class1 to null.
Any thoughts on this?
Well, you intialize it actually class1 = new Class1(); here, according to the code provided.
You first set it to null
Form1.class1 = null;
after
class1 = new Class1(); //INIT THE SAME (ACCORDING TO THE NAME) OBJECT
class1.showMSG(); //CALL A METHOD ON IT.
EDIT
According to edited question:
public Class1()
{
Form1.class1 = null;
}
doesn't reset anything as you're still inside a constructor, on exit from it actually object will be constructed and assigned to the same object you assigned null before.
Class1's constructor sets
Form1.class1 = null;
But when you execute
class1 = new Class1();
the assignment to class1 (which is the same class1) happens after the constructor executes. So Form1.class1 now has a value.
Maybe it's easiest to explain if you break up your last two lines, into:
var tmp = new Class1(); // makes class1 null
class1.showMSG(); // would raise exception, remove this line to proceed
class1 = tmp; // class1 is no longer null
class1.showMSG(); // no exception, instance exists to call method on