Could you please explain the following behavior of C# Class. I expect the classResult as "Class Lijo"; but actual value is “Changed”.
We’re making a copy of the reference. Though the copy is pointing to the same address, the method receiving the argument cannot change original.
Still why the value gets changed ?
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
String nameString = "string Lijo";
Person p = new Person();
p.Name = "Class Lijo";
Utilityclass.TestMethod(nameString, p);
string classResult = p.Name;
Response.Write(nameString + "....." + classResult);
}
}
public class Utilityclass
{
public static void TestMethod(String nameString, Person k)
{
nameString = "Changed";
k.Name = "Changed";
}
}
public class Person
{
public string Name
{
get; set;
}
}
Update: When I pass a String, it does not get actually changed.
The briefest answer is: read my article on parameter passing which goes into this in a fair amount of detail.
The slightly longer answer is to compare these two methods, both of which use value parameters:
public void ChangeMe(string x)
{
x = "changed";
}
public void ChangeMe(Person x)
{
x.Name = "changed";
}
In the first case, you are changing the value of the parameter. That is completely isolated from the original argument. You can't change the content of the string itself, because strings are immutable.
In the second case, you are changing the contents of the object which the parameter's value refers to. That's not changing the value of the parameter itself - it will be the same reference. To give a real world example, if someone delivers something to your house that changes the contents of your house, but it doesn't change your house's address.
If you changed the second method to this:
public void ChangeMe(Person x)
{
x = new Person("Fred");
}
then the caller wouldn't see any change. This is closer to what you're doing with a string - you're making the parameter refer to a different object, rather than changing the contents of the existing object.
Now, when you use a ref parameter, the variable used by the caller as the argument is "aliased" with the parameter - so if you change the value of the parameter, that changes the value of the argument as well. So if we change the last method like this:
public void ChangeMe(ref Person x)
{
x = new Person("Fred");
}
then:
Person y = new Person("Eric");
ChangeMe(ref y);
Console.WriteLine(y.Name);
this will print out "Fred".
The key concept to understand is that the value of a variable is never an object - it's either a value type value or a reference. If an object's data is changed, that change will be visible through other references. Once you understand that copying a reference isn't the same as copying an object, the rest falls into place reasonably easily.
Person is a reference type, so no matter whether you use ref, out or nothing, you will always be able to modify it inside the method. You never pass the real person object to the method, you are passing the pointer as reference but not the actual Person. The ref keyword is useful with value types (such as structs, int, float, DateTime, ...). It could also be used with reference types but only to indicate behavior but cannot enforce it. If you use it with reference types it allows you to change the object this reference is pointing to.
When you pass P to a test method you pass its location in the memory, rather than the copy of the object. Reference gets picked up in the body of the method and the original value gets modified.
Utilityclass.TestMethod cannot change the local variable p to point to a different Person object since you are not passing by reference, but it is still free to call any methods or change any properties on the object it is passed. So the Name property can be modified within Utilityclass.TestMethod.
This question has been mostly answered, but I think you might like to try out this snippet (bonus points if you try this out with ints!)
class Program
{
static void Main(string[] args)
{
Person p = new Person();
p.Name = "Class Lijo";
Utilityclass.TestMethod(p);
string classResult = p.Name;
Console.WriteLine(classResult);
Utilityclass.TestMethod2(ref p);
classResult = p.Name; // will bomb here
Console.WriteLine(classResult);
}
}
public class Utilityclass
{
public static void TestMethod(Person k)
{
k.Name = "Changed";
k = null;
}
public static void TestMethod2(ref Person k)
{
k.Name = "Changed Again!";
k = null;
}
}
When you pass a reference type argument to a method, this means that the method has direct access to that argument not to a copy of it....
So the result is Changed.
Related
So basically I have a class NodeTree:
public class NodeTree
{
public NodeTree(int value, NodeTree left, NodeTree right)
{
Value = value;
Right = right;
Left = left;
}
public int Value { get; set; }
public NodeTree Right { get; set; }
public NodeTree Left { get; set; }
}
And in my main I want to do something like
NodeTree root = null;
Algo.InsertValueIt(root, 8);
Where InsertValueIt() is a method from my static class Algo which does :
public static void InsertValueIt(NodeTree root, int val)
{
var newNode = new NodeTree(val, null, null);
if (root == null)
{
root = newNode;
}
}
Everything is working as expected in my method, but back to my main, my object root is still null.
The reason I am confused is that I give to my method a reference, so it should modify the value of the adress to the new space I am allocating.
I think I can solve my problem by just returning a NodeTree, but is there a way of doing it with a void return type?
You need to define your argument to be passed by reference in order to modify the original value (note the ref keyword):
public static void InsertValueIt(ref NodeTree root, int val) {
...
Also when calling the method, you need to mark the parameter with ref:
Algo.InsertValueIt(ref root, 8);
... otherwise you only modify the local copy in that function.
What happens when you pass a reference type to a method?
The variable declared to be of a reference type holds the memory address where the instance of the type has been allocated (the root in the calling code). The value of this address is copied to a new variable created on the stack for the called method (the root in the InsertValueIt). Using that address through the new variable you will be able to change every public property of the instance or call any methods (provided that the address passed is not null).
What happens now if you call new on this local variable?
A new block of memory is allocated on the heap for the type, the constructor is called to initialize everything, and the memory address of this block is stored in the LOCAL variable inside the InsertValueIt.
Your original one, (the root in the calling code), is unaffected by this change. (still holds null). Using the ref keyword makes the this 'problem' disappear, but I suggest to use a method that creates the Node and return it to the calling method instead.
If you want to understand in more depth this subject I recommend these two articles:
C#Concepts: Value Types vs Reference Types from Joseph Albahari
Parameter Passing in C# from Jon Skeet
Your root value assigned in InsertValueIt is not used in any execution path, so you should add the ref keyword in the parameter declaration
I have two viewState properties.
One is a List<MyObject> MyObjects
And another one is MyObject SelectedObject
Whenever user selects an object from the list, I assign it to SelectedObject like this:
SelectedObject = MyObjects.Where(x=>x.MyId ==IdSelectedInUI)
This allows me easy manipulation of the SelectedObject.
Now, When I change SelectedObject's properties, how Can I assign those properties back to the original object in the list? I was thinking to use ref, but cannot quite figure it out.
Edit
All of the objects are classes, not structs.
So, here's what I have:
//Children are of type =List<MyParentObject.ChildObject>
public MyParentObject MyParent
{
get
{
if (ViewState["MyParent"] == null)
{
MyParent= GetItemsFromDatabase();
}
return (TaskInfo)ViewState["MyParent"];
}
set
{
ViewState["MyParent"] = value;
}
}
public MyParentObject.ChildObject SelectedChild
{
get
{
return (MyParentObject.ChildObject)ViewState["Child"];
}
set
{
ViewState["Child"] = value;
}
}
protected onButtonClick()
{
SelectedChild = MyParent.Children.Where(x=>x.Child_Id == Convert.ToInt32(txt.Text)).FirstOrDefault();
SelectedChild.Property2 = "test2" //OldValue "test1"
//now if I run
MyParent.Children.Where(x=>x.Child_Id ==Convert.ToInt32(txt.Text)).Select(x=>x.Property2) //Shows "test1" and I expect "test2"
}
}
SelectedObject is an object reference. It is identical with the original object in the list - SelectedObject and the "original" object are the same object. If you are seeing behavior that indicates otherwise, please update your question.
It depends. Assuming MyObject is a class, it is passed "by value", but the value being passed is a reference to the original object.
For instance:
void Mutate(SomeObject x)
{
x.val = "banana";
}
void Reassign(SomeObject x)
{
x = new SomeObject();
x.val = "Garbage";
}
public static void Main()
{
SomeObject x = new SomeObject();
x.val = "Apple";
Console.WriteLine(x.val); // Prints Apple
Mutate(x);
Console.WriteLine(x.val); // Prints banana
Reassign(x);
Console.WriteLine(x.val); // Still prints banana
}
This is how passing objects works in C#. You can modify the contents, but not the "value" of the object itself (which is a pointer to it in memory).
If you are looking to change the contents of the object, nothing special needs to be done.
Passing an object by ref parameter will allow you to reassign the reference to it. For example, if:
void Reassign(ref SomeObject x) // implementation
Was used in the previous example, the print out of the final WriteLine would have been "Garbage", as the reference itself was changed, and due to the ref parameter, this changed the reference in the caller as well.
+Edit
If MyObject is a struct, however, the structure is copied when passed, and reassigning it inside a different scope will have no effect on the original structure.
What you could do for this is to have a function return the structure and assign it:
MyStruct Mutate(MyStruct x){}
// calling
myStruct = Mutate(myStruct);
Or do it by reference parameter.
Is there a way in C# to create a field which is a reference to another field which is a value type?
class myClass
{
bool b1;
public void method1(ref bool b)
{
b1 = b;
}
}
I want b1 to reference the value of b, just as b references the value of the original argument, so that changes to b1 will affect the original argument.
EDIT:
What I’m trying to achieve is a myCheckBox class which automatically updates a field. See: How do I change a value argument from within an event handler?
Sure! Take a look at Eric's answer to this question:
Setting a ref to a member field in C#
As others have pointed out, you cannot store a reference to a variable
in a field in C#, or indeed, any CLR language.
Of course you can capture a reference to a class instance that
contains a variable easily enough
Well... there is a very contort way :) of course.
That is, using reflection!
You cannot get the address of a field, but we can use reflection.
Reflection is slower than accessing directly a field, i warn you.
And really, accessing private fields of other classes is a really bad practice!
Is however useful sometime for some dirty hacks when you don't have control of code written by other people.
Here the example, but i keep saying, it is not a good practice, is here only for curiosity and for educational purposes!
Fine another way to access your field, using properties or using a class that modify your properties.
// Our FieldReference class that internally uses reflection to get or set a field value.
public class FieldReference<T>
{
private object ownerObject;
private FieldInfo fieldInfo;
public FieldReference(object ownerObject, string fieldName)
{
this.ownerObject = ownerObject;
this.fieldInfo = ownerObject.GetType().GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
}
public FieldReference(object ownerObject, FieldInfo fieldInfo)
{
this.ownerObject = ownerObject;
this.fieldInfo = fieldInfo;
}
public T Value
{
get { return (T)this.fieldInfo.GetValue(this.ownerObject); }
set { this.fieldInfo.SetValue(this.ownerObject, value); }
}
}
// Our dummy class
public class MyClass
{
// Our field we want to expose.
private int myField;
public MyClass(int value)
{
this.myField = value;
}
// Just a function we use to print the content of myField.
public override string ToString()
{
return this.myField.ToString();
}
}
class Program
{
public static void Main()
{
// We create our class.
MyClass mc = new MyClass(5);
// We print field value, should be 5 :)
Console.WriteLine(mc.ToString());
// We create our field reference
FieldReference<int> fieldref = new FieldReference<int>(mc, "myField");
// We set the value using field reference.
// Note, we accessed a private field :)
fieldref.Value = 100;
// Now we print the value, should be 100!
Console.WriteLine(mc.ToString());
Console.ReadLine();
}
}
Looks like something that is better solved using delegates/events.
Instead of trying to do the impossible (force value types to behave as reference types), use an event and fire it whenever this value is changed.
Subscribe to this event from the caller/s and you are good to go.
Not knowing what you would want this for you could use a delegate for this, it does sound like a code smell though:
class myClass
{
Action<bool> modify;
public void method1(Action<bool> modify)
{
this.modify = modify;
}
public void ModifyIt()
{
modify(false);
}
}
bool b1 = true; //b1 is true
var m = new myClass();
m.method1(val => { b1 = val; });
m.ModifyIt(); //b1 is false now
I have the following class:
public class Person
{
public String Name { get; set; }
}
I have a method that takes in Person and a String as parameters:
public void ChangeName(Person p, String name)
{
p.Name = name;
}
Since Person was passed by reference, it should change the Name of the passed instance.
But is this method more readable than the one above?
public Person ChangeName(Person p, String name)
{
p.Name = name;
return p;
}
Is it more readable? No. In fact you may be doing more harm them good.
By having it return a Person object, it might lead you to believe that instead of modifying the Person parameter, it is actually creating a new Person based on p but with a different name and someone could incorrectly assume that p is never changed.
Either way, if you have a method that has no affect on the class it is apart of it should probably be static. That helps you know for sure that it doesn't affect its class. Only have the method return a value if you need it to return a value.
So here is my recommendation for this method:
public static void ChangeName(Person p, String name)
{
p.Name = name;
}
There isn't anything right/wrong with either approach. Depends on what your program needs.
Returning the parameter passed into a method is rarely needed as it is always possible for the user to just use the variable passed as argument instead.
It, however, gives you the flexibility of eventually overriding this implementation, or passing this implementation into another function which accepts delegates with similar signatures. Then you can pass in other implementations that does not return the same Person object.
Do it only if you really need the flexibility.
I would suggest you use one of the following for best readability:
public static void ChangeName(Person p, String name)
{
p.Name = name;
}
public static Person WithName(Person p, String name)
{
return new Person(p) { Name = name };
}
The second one treats the Person object as immutable and does not change the state of the object. The ChangeName function explicitly changes the state of the input object. I think it's important to make a clear distinction between the two types of methods. A good rule of thumb to follow is that a method should not change the state of an object AND return one at the same time.
first of all p is not being passed by reference in the first example. Your second method makes one believe that it is returning a new reference which it is not. So I don't think the second one is any clearer than the first one.
In the case you've described, I would say neither. Its not really clear what you are trying to do with this method. Just use the object and set the property. Inserting a method into the execution path just complicates understanding and creates another dependency on the Person object and its underlying value.
If you are asking a meta question that involves some design over and above the code you have posted, then I am missing it.
The first one is better, because of that the second one might lead you to believe that p is immutable.
But, the whole method is useless since it just calls the setter. Why not just call the setter directly?
I beleve that your 2nd approach is not more readable YAGNI. But if you change it like this
public static class PersonExtensions
{
public static Person ChangeName(this Person p, String name)
{
p.Name = name;
return p;
}
you will have an extensionmethod for a fluent interface a la
new Person().ChangeName("Peter Smith").SendEmail().Subject("Test Mail").Receiver("....)
Here is the definitive reference to understand passing parameters by value/reference.
Looking at the code, why don't you use property?
public string Name
{
set {name = value;}
get { return name; }
}
EDIT: Auto implemented properties
public string Name
{
set;
get;
}
I'm trying to return a reference to an object, not pass it by value. This is due to not being able to pass a property by reference.
How can I get the code below to write 'new number plate' not 'old number plate'. After a bit of looking it seems like I cant. Just wanted to be sure first. Seems odd you cant.
Cheers
Steve
http://hardcode.ro/archive/2008/03/18/c-return-reference-types.aspx
Link
public partial class Test2 : DefaultPage
{
protected void Page_Load(object sender, EventArgs e)
{
var car = new Car();
var numberPlate = car.GetNumberPlate();
numberPlate = "new number plate";
Response.Write(car.GetNumberPlate());
}
}
}
public class Car
{
private string _numberPlate;
public Car()
{
_numberPlate="old number plate";
}
public string NumberPlate
{
get { return _numberPlate; }
set { _numberPlate = value;}
}
public string GetNumberPlate()
{
return _numberPlate;
}
}
You're doing this a little backwards. If you want to change the value for that you need to actually change the property on the object.
car.NumberPlate = "old number plate";
Response.Write(car.GetNumberPlate());
If you're wanting to work with references you can use the ref keyword. This may not be what you're looking for though.
You need to become clearer in your mind about the difference between objects and references. Your property already returns a reference to the string containing the current numberplate. It can't possibly return the object itself, because string is a reference type. (Even if you used a value type, the property would only be returning a copy of the data, so change to the variable's value still wouldn't affect the property.)
What you seem to want isn't a reference to the object but a reference to the property. There's no way of doing that in C# - and this is a good thing in my view, as it promotes readability. The kind of code you're trying to write in your example is much more complicated to understand, because assigning a value to a normal variable could do anything.
For more information, see my article about value types and reference types.
protected void Page_Load(object sender, EventArgs e)
{
var car = new Car();
car.NumberPlate = "new number plate";
Response.Write(car.NumberPlate);
}
Your GetNumberPlate() method seems superfluous.
If you're using C# 3 or 3.5, I would rewrite this as:
public partial class Test2 : DefaultPage
{
protected void Page_Load(object sender, EventArgs e)
{
var car = new Car();
car.NumberPlate = "new number plate";
Response.Write(car.NumberPlate);
}
}
public class Car
{
public Car()
{
NumberPlate="old number plate";
}
public string NumberPlate { get; set; }
}
Since strings are immutable you can't do this. The value that you get back in this line:
var numberPlate = car.GetNumberPlate();
Is a reference to all intents and purposes (in that the value of the string is not copied to a different memory address), but this line
numberPlate = "new number plate";
Is semantically the same as:
numberPlate = new string("new number plate");
Which causes that reference to point to a different string.
Are you looking to pass the property the same way you might pass a method into a function? For methods you'd do something like this;
// fn takes a method which returns string, calls it, and prints it.
void PrintsAMethodsResult(Func<string> GetString)
{
Console.WriteLine( GetString() );
}
// calls like this;
PrintsAMethodResult( Car.GetNumberPlate );
But if you want to do it with a property, you've got a bit of a mess; properties are really just two methods (a getter and a setter, of type Func<T> and Action<T>) so you have to write different things do deal with the setter and the getter. A getter property can be called like this;
PrintsAMethodResult ( () => Car.NumberPlate );
This works the same as the GetNumberPlate method, by creating a function which takes no parameters and returns the car's number plate, effectively converting the property into a function.
There is no nicer way of passing the getter property as though it were a method.
Create another class within "Car" and then return it. That should do just fine. Although possibly you don't want to this since it's not a good way to code.