Reputation: 2830
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"??
Upvotes: 0
Views: 146
Reputation: 66388
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:
test objtest = new test();
New instance of the class test
is being created and assigned address in the memory. Every time you refer to the variable objtest
, that address will be used for example:
objtest.Name = "vikas";
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:
private static void Test(test objtest)
The actual parameter that is passed "behind the scenes" is the address of the instance in the memory. Whenever you refer to the parameter objtest
inside the function, the runtime engine will go to the address passed as the actual parameter. So having this line inside the function:
objtest.Name = "chetan";
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 ref
or not, as you are dealing with reference type.
However, being passed by value (e.g. without ref
keyword) 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:
objtest = null;
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:
private static void Test(ref test objtest)
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.
Upvotes: 1
Reputation: 5760
Well, you're using an object with a value of null
, which causes the exception. null
for reference types means "points to zero". When you're trying to access the value stored at address zero, you get a NullReferenceException
.
You're setting objtest
to null
before you access the Name
property, so you're trying to access the Name
property of the object stored at address zero, which makes no sense.
Upvotes: 0
Reputation: 19296
You have problem here with passing parameter to function.
Default parameters are passed by value.
The attempt to reassign the parameter to a different memory location only works inside the method Test
and does not affect the original variable objtest
in Main method.
So when you add ref
to parameter in Test
function in two cases behaviour will be the same, because all of the changes that take place inside the method Test
affect the original object objtest
in Main method.
First example from your question with ref parameter:
class Program
{
static void Main(string[] args)
{
test objtest = new test();
objtest.Name = "vikas";
Test(ref objtest);
//objtest = null; when I uncomment this line it shows me exception
Console.WriteLine(objtest.Name);
Console.ReadLine();
}
private static void Test(ref test objtest)
{
objtest.Name = "chetan";
objtest = null;
}
}
class test
{
private string _Name = string.Empty;
public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
}
}
}
In the second example first you set null to original object and after that you want read property Name, so you will get NullReferenceException
.
Upvotes: 0