I have a program like this
class Program
{
static void Main(string[] args)
{
test objtest = new test();
objtest.Name = "vikas";
Test(objtest);
//objtest = null; when I uncomment this line it shows me exception
Console.WriteLine(objtest.Name);
Console.ReadLine();
}
private static void Test(test objtest)
{
objtest.Name = "chetan";
objtest = null;
}
}
class test
{
private string _Name = string.Empty;
public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
}
}
}
Output:
chetan
Second program:
class Program
{
static void Main(string[] args)
{
test objtest = new test();
objtest.Name = "vikas";
Test(objtest);
objtest = null;
try
{
Console.WriteLine(objtest.Name);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException + " " + ex.Message);
}
Console.ReadLine();
}
private static void Test(test objtest)
{
objtest.Name = "chetan";
objtest = null;
}
}
class test
{
private string _Name = string.Empty;
public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
}
}
}
Output:
Object reference not to set an instance of object
Why?
When I set objtest = null; in Test it shows me the value, but when I set null in same it shows me error.
Added after @kmatyaszek post:
In first program
static void Main(string[] args)
{
test objtest = new test();
objtest.Name = "vikas"; // **I am assigning this value**
Test(objtest);
//objtest = null; when I uncomment this line it shows me exception
Console.WriteLine(objtest.Name);
Console.ReadLine();
}
private static void Test(test objtest)
{
objtest.Name = "chetan";
objtest = null;
}
Why it is displaying “chetan” not “vikas”??
Classic confusion caused by reference type that is being passed by value.
I will give a rather short and simple answer here; those interested to learn more and in depth are more than welcome to read Jon Skeet article on Parameter passing in C# and similar article with diagrams, by Lee Richardson.
Reference type, in short, is any type that is not primitive or struct. Any custom defined class is hence a reference type.
When instance of such class is passed to a function, what actually happens is that a pointer to this instance is passed. More accurately, a copy of the pointer is being passed since by default parameters are passed by value.
When you have this line:
New instance of the class
testis being created and assigned address in the memory. Every time you refer to the variableobjtest, that address will be used for example:The runtime engine will go the address assigned when the instance was created, look for the place reserved for the property Name and change the contents there to “vikas”. The change is immediate and permanent for this instance.
When you have such function signature:
The actual parameter that is passed “behind the scenes” is the address of the instance in the memory. Whenever you refer to the parameter
objtestinside the function, the runtime engine will go to the address passed as the actual parameter. So having this line inside the function:Is exactly the same as having it outside the function: it will look for the place reserved for the property Name in the memory address passed, and change the contents there to “chetan”. Yet again, this change is immediate and permanent for that instance. For this thing (changing properties) it doesn’t matter if you’re using
refor not, as you are dealing with reference type.However, being passed by value (e.g. without
refkeyword) means that the memory address is being copied and the function only get the copy, very much like passing integer. Any change to the copy will not affect the original value. Thus, when you have this line inside the function:You change the copy to point on nothing, however the variable outside the function still point to the same address and won’t be null.
If you have such function signature:
Then it means the address itself is passed by reference, hence changing the variable holding the address will cause it to be changed outside the function as well.
This pretty much sums it up, I don’t bring anything new here just clarifying things with what I deem more simple explanation.