Assign object by reference - c#

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.

Related

Unexpected behavior with Struct internal values

*Solved. Thanks for the explanations guys, I didn't fully understand the implications of using a value type in this situation.
I have a struct that I'm using from a static class. However, the behavior is showing unexpected behavior when I print it's internal state at runtime. Here's my struct:
public struct VersionedObject
{
public VersionedObject(object o)
{
m_SelectedVer = 0;
ObjectVersions = new List<object>();
ObjectVersions.Add(o);
}
private int m_SelectedVer;
public int SelectedVersion
{
get
{
return m_SelectedVer;
}
}
public List<object> ObjectVersions;//Clarifying: This is only used to retrieve values, nothing is .Added from outside this struct in my code.
public void AddObject(object m)
{
ObjectVersions.Add(m);
m_SelectedVer = ObjectVersions.Count - 1;
}
}
Test code
VersionedObject vo = new VersionedObject(1);
vo.AddObject(2);//This is the second call to AddObject()
//Expected value of vo.SelectedVerion: 1
//Actual value of vo.SelectedVersion: 1
Now, if you test this code in isolation, i.e., copy it into your project to give it a whirl, it will return the expected result.
The problem; What I'm observing in my production code is this debug output:
objectName, ObjectVersions.Count:2, SelectedVer:0,
Why? From my understanding, and testing, this should be completely impossible under any circumstances.
My random guess is that there is some sort of immutability going on, that for some reason a new struct is being instanced via default constructor, and the ObjectVersions data is being copied over, but the m_SelectedVersion is private and cannot be copied into the new struct?
Does my use of Static classes and methods to manipulate the struct have anything to do with it?
I'm so stumped I'm just inventing wild guesses at this point.
Struct is value type. So most likely you are creating multiple copies of your object in your actual code.
Consider simply changing struct to class as content of your struct is not really good fit for value type (as it is mutable and also contains mutable reference type).
More on "struct is value type":
First check FAQ which have many good answers already.
Value types are passed by value - so if you call function to update such object it will not update original. You can treat them similar to passing integer value to function: i.e. would you expect SomeFunction(42) to be able to change value of 42?
struct MyStruct { public int V;}
void UpdateStruct(MyStruct x)
{
x.V = 42; // updates copy of passed in object, changes will not be visible outside.
}
....
var local = new MyStruct{V = 13}
UpdateStruct(local); // Hope to get local.V == 42
if (local.V == 13) {
// Expected. copy inside UpdateStruct updated,
// but this "local" is untouched.
}
Why is this a struct and not a class? Even better, why are you tracking the size of the backing store (List<T>) rather than letting the List<T> track that for you. Since that underlying backing store is public, it can be manipulated without your struct's knowledge. I suspect something in your production code is adding to the backing store without going through your struct.
If it were me, I'd set it up something like this, though I'd make it a class...but that's almost certainly a breaking change:
public struct VersionedObject
{
public VersionedObject()
{
this.ObjectVersions = new List<object>() ;
return ;
}
public VersionedObject(object o) : this()
{
ObjectVersions.Add(o);
return ;
}
public VersionedObject( params object[] o ) : this()
{
ObjectVersions.AddRange( o ) ;
return ;
}
public int SelectedVersion
{
get
{
int value = this.ObjectVersions.Count - 1 ;
return value ;
}
}
public List<object> ObjectVersions ;
public void AddObject(object m)
{
ObjectVersions.Add(m);
return ;
}
}
You'll note that this has the same semantics as your struct, but the SelectedVersion property now reflects what's actually in the backing store.

Do C# properties hide instance variables or is something deeper going on?

Consider the class:
public class foo
{
public object newObject
{
get
{
return new object();
}
}
}
According to MSDN:
Properties are members that provide a flexible mechanism to read,
write, or compute the values of private fields. Properties can be used
as though they are public data members, but they are actually special
methods called accessors. This enables data to be accessed easily
And:
Properties enable a class to expose a public way of getting and
setting values, while hiding implementation or verification code.
A get property accessor is used to return the property value, and a
set accessor is used to assign a new value. These accessors can have
different access levels. For more information, see Accessor
Accessibility.
The value keyword is used to define the value being assigned by the
set indexer.
Properties that do not implement a set method are read only.
while still providing the safety and flexibility of methods.
Does this therefore mean that at some point in time the value of the newObject property has a reference to the returned new object?
edit removed readonly from property
edit2 also would like to clarify that this is not the best use for a property but its done to try and illustrate the question more effectively.
You return a new object on each access to the property and that is not the expected behavior of properties. Instead you should return the same value each time (e.g. a value stored in a field). A property getter is simply glorified syntax for a method that returns a value. Your code compiles into something like this (the compiler creates a getter by prefixing the property name with get_ which is then emitted as IL):
public class foo
{
public object get_newObject()
{
return new object();
}
}
Each call to the getter will create a new object that foo doesn't know about or has access to.
Does this therefore mean that at some point in time the value of the newObject property has a reference to the returned new object?
No.
Property using a backing field:
class Foo {
readonly Object bar = new Object();
public Object Bar { get { return this.bar; } }
}
Using automatic properties:
class Foo {
public Foo() {
Bar = new Object();
}
public Object Bar { get; private set; }
}
A property is accessed using the same easy syntax as a public field. However, by using a property you can add code to the getter and the setter allowing you to do stuff like lazy loading in the getter or validation in the setter (and much more).
Under the hood, your property will simply be calling a function named get_newObject() that looks like this:
public object get_newObject()
{
return new object();
}
Since that is the case, it will always return a new object every time it is invoked.
If you want to retain a reference to the object, then I would recommend creating a private field to hold the data and having the property access that field, like so:
private object myObject;
public object newObject
{
if(myObject == null)
{
myObject = new object();
}
return myObject;
}
Since your property doesn't define set, and your field is private, newObject is basically eradonly outside of the containing class.
Properties in C# are "syntactic sugar". The code within the get block of a property is in fact put into a hidden get_PropertyName() method, and the set block into a hidden set_PropertyName() method. In the case of your code, the following method will be created:
public object get_newObject()
{
return new object();
}
You can see these hidden methods if you view the compiled assembly using Reflector, or ildasm.
When the property is used, the C# compiler converts any "get" accesses of your property into calls of the get_newObject() method. As an example:
If you were to write the following:
var foo = new foo();
var aNewObject = foo.newObject;
The compiler would convert that to:
var foo = new foo();
var aNewObject = foo.get_newObject();
So, in answer to your other question, the newly created object returned when someone "gets" the property won't be stored within your foo instance, the caller will simply get a new object every time.
Not exactly. Properties are just syntactic sugar so that you don't have to write accessor methods (like Java).
So this:
private int _myInteger;
public int MyInteger
{
get { return _myInteger; }
set { _myInteger = value; }
}
is equivilant to this:
private int _myInteger;
public int GetMyInteger()
{
return _myInteger;
}
public void SetMyInteger(int value)
{
_myInteger = value;
}
and it gets better with this, which is also equivilant:
public int MyInteger { get; set; }

How to check if a variable is Array or Object?

For deserialising a json object, I had to define a parent class that would contain an object or an array of objects for the child class. It has to be an object if an object was retrieved, or an array of objects if an array was retrieved from the json.
JSON array object
{"y":{"x":[{"data":28}, {"data":56}, {"data":89}]}}
JSON object
{"y":{"x":{"data":28}}}
y is receiving x at a time, and x[] at another time. There is no such condition to determine whether y would recieve an array or an object.
Hence for determining whether I received an array or not, I am checking the IsArray() condition.
I tried
class Y
{
public X x { get { return System.IsArray() ? new X() : new x[] }; set; }
}
class X
{
public int data { get; set; }
}
It isnt working.
System.IsArray() isn't being recognised??
First off, an array is an object. That's a good thing, since it allows these functions to work (both assume using System;):
bool IsArray(object o) { return o is Array; }
bool IsArray(object o) { return o.GetType().IsArray; }
Second, if you want a property whose type can be either X or X[], the property's type needs to be object:
class Y
{
private object _x;
public object x {
get { return _x; }
set
{
if (value.GetType != typeof(X) && value.GetType != typeof(X[]))
throw new ArgumentException("value");
_x = value;
}
}
}
This somewhat ignores the advantage of static typing, as you're using object and checking types at run time. It would really be much simpler to define the property as an array, even for those cases where there's only one value. In such cases, it would be an array whose length is 1.
I've been using the Json.NET Nuget package, and it's been really easy to work with:
string jsonStr = "{'y':{'x':[{'data':28}, {'data':56}, {'data':89}]}}";
dynamic jobject = JsonConvert.DeserializeObject(jsonStr);
bool isArray = jobject.y.x.Type == JTokenType.Array;
bool isObject = jobject.y.x.Type == JTokenType.Object;
Hope this helps!
the property x of Type X in class Y cannot be an array of X if you explicity state it is of type X. Declaring it as an object would be one way to get round this.
If you want to check it is an array I would use a backing field (say _x) and then where you use the property do a check (typeof(_x) == X[])
That could get messy though, my best advice would be set the type of property x to X[] and in the set determine whether the value was an array (if so just set _x = value) or if not add value to an empty array of X
You can try this...
if (obj.GetType().IsArray)
{
...
}
Another way you can do it is,
if (obj is Array) {
...
}

How to create a reference to a value-field

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

lPass by value & Pass by Reference

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.

Categories