Updating One Object Updates the Other somehow - c#

I have two objects, yet when i update one, the other item with the same GUID gets updated as well even though i am trying to apply a new GUID so that i can separate them out.
var completedSecond = model.CompletedTransfers.First();
var transferedTransfers = model.TransferedTransfers.First();
if (transferedTransfers.Count != 0) {
transferedTransfers.RowId = Guid.NewGuid();
}
When i run this code, the two items have the same GUID, yet when i update the second one to have a new GUID, the first object also gets that new GUID. How is this possible?

You don't have 2 objects but 2 references to the same object in memory. In C# classes are reference types meaning that your completedSecond is referencing an object in memory, that in this case is the same as the object transferedTransfers is referenceing to.
In order to get 2 different object you need to instantiate a new object
By implementing the ICloneable interface
public class MyClass : ICloneable
{
public Guid Id { get; set; }
public object Clone()
{
return new MyClass { Id = Id };
}
}
Another way is to have a copy constructor:
public class MyClass
{
public Guid Id { get; set; }
public MyClass() { }
public MyClass(MyClass other)
{
Id = other.Id;
}
}
Read this for the differences between the two ways: Copy constructor versus Clone()
In addition, when talking about coping of objects you have what is called deep-copy and shallow-copy. More on these you can find here:
Shallow copy or Deep copy?
Object.MemberwiseClone Method

That happens because the model.TransferedTransfers object is passed by reference, not by value. the variable completedSecond and transferedTransfers both points to model.CompletedTransfers. Also be aware of naming smells (transferedTranfers)

Related

Navigating between ContentPages with Prism in Xamarin Forms maintains NavigationParameters

Using the NavigationParameters collection within Prism, we are passing an object from one ContentPage to another ContentPage which displays as a modal.
The modal allows a user to edit the data. If the user decides to cancel the edit form, we call:
NavigationService.GoBackAsync(null, true).
Once navigated back to the previous page, the original property that was passed through to the modal has updated with the edited values without setting it.
Are NavigationParameters passed as a reference within NavigateAsync? What’s the best way of preventing this from happening?
Using the NavigationParameters collection within Prism, we are passing an object [...] [Emphasis mine]
You are setting an object in the NavigationParameters. Instances of classes (objects) are passed by reference in C#, instances of structures are passed by value. For structures there are semantics to copy and compare values (i.e. all public properties are copied and compared respectively), but for classes there are no similar semantics.
Please see the documentation:
Because classes are reference types, a variable of a class object holds a reference to the address of the object on the managed heap. If a second object of the same type is assigned to the first object, then both variables refer to the object at that address.
In order to prevent the original object being updated, you'll have to copy the object before it is manipulated (I'd copy it before passing it, but you could copy it at the target site, too). If your class contains value type properties only, a shallow copy will suffice, i.e. you create a method (or property, but this might be misleading) that returns a new object of your class with all the values copied
class MyClass
{
int Value1 { get; set; }
float Value2 { get; set; }
public MyClass Copy()
{
var copy = new MyClass()
{
Value1 = this.Value1,
Value2 = this.Value2
}
return copy;
}
}
If you object contains reference types itself, you might have to create a deep copy
class MyClass
{
MyClass2 Reference { get; set; }
public MyClass Copy()
{
var copy = new MyClass()
{
Reference = this.Reference.Copy()
}
return copy;
}
}
Of course, those will have to implement a Copy() method, too.

Variables from a specific class equality both sides still changing together if one of the sides change

I am new to C# and WPF, and I am trying to define a new variable from a class and to give this new variable a value from an old variable and then make some changes to the new one. But the problem is that the new variable is still connected to the old variable and if I change anything in the new one, the changes will effect the old one:
MW.CurrentPreviewJob = addjob;
MW is another page than the page I am writing the code in,
and I define them as follows:
public static Job addjob;
public Job CurrentPreviewJob
{
get { return _currentPreviewJob; }
set {
_currentPreviewJob = value;
this.NotifyPropertyChanged("CurrentPreviewJob");
}
}
the class for the two variables is same and it is:
public partial class Job
{
public int JOB_ID { get; set; }
public string JOB_DESCRIPTION { get; set; }
public byte[] TARGET_IMAGE { get; set; }
public int JOB_USER { get; set; }
}
So how can I take the value of CurrentPreviewJob without stay connecting to it?
This is because an object of a class is a reference type.
Let's take a look at an example:
We create an object of your class:
Job someJob = new Job();
What exactly is someJob? Well, when you create an instance of an object it is held in special area of memory, and someJob holds a reference to it (which is an address under which the program can find the instance in the memory).
So when you do something like:
Job someOtherJob = someJob;
you actually tell someOtherJob object to hold reference to the same address in a memmory as someJob object. that's how reference types work.
Now, if you do, for example:
someOtherJob.JOB_DESCRIPTION = "I changed that description in some other job object";
This is what happens: program checks the address which is referenced by somOtherJob object, goes there, finds the instance, and change its JOB_DESCRIPTION property's value. BUT remember that someJob objct (the "old" one) has a reference to the same instance in the memory - hnce, it will have the same, changed JOB_DESCRIPTION.
The most elegant thing to do here is to implement some kind of cloning method on the Job class.
public partial class Job
{
public int JOB_ID { get; set; }
public string JOB_DESCRIPTION { get; set; }
public byte[] TARGET_IMAGE { get; set; }
public int JOB_USER { get; set; }
public Job Clone() {
Job clone = new Job();
clone.JOB_ID = this.JOB_ID;
clone.JOB_DESCRIPTION = this.JOB_DESCRIPTION;
clone.TARGET_IMAGE = this.TARGET_IMAGE;
clone.JOB_USER = this.JOB_USER;
return clone;
}
}
and use it like:
Job someOtherJob = someJob.Clone();
That happens because both CurrentPreviewJob and addjob are reference types. They both reference the same object in the memory. So whatever you do to one variable will also affect the other, since they are pointing to the same object. You can make your Job have a Clone method like this:
public partial class Job
{
public int JOB_ID { get; set; }
public string JOB_DESCRIPTION { get; set; }
public byte[] TARGET_IMAGE { get; set; }
public int JOB_USER { get; set; }
public Job Clone()
{
return new Job {
JOB_ID = this.JOB_ID,
JOB_DESCRIPTION = this.JOB_DESCRIPTION,
TARGET_IMAGE = this.TARGET_IMAGE,
JOB_USER = this.JOB_USER
};
}
}
Then you can assign your CurrentPreviewJob like this:
MW.CurrentPreviewJob = addjob.Clone();
This will make another object so your second variable is no longer linked to your previous.
Or another way is to make your class a struct
The problem is because Job is a class, and classes are reference types, meaning that if you assign one job variable to another, you just have too variables referencing the same data.
You could declare Job as a struct, which are value types and assignment would automatically create a copy.
I tend to avoid structs, simply because I don't like having to copy things around just to change properties, so I'd suggest adding an appropriate constructor to Job, like:
public Job(Job other) {
this.JOB_ID = other.JOB_ID;
this.JOB_DESCRIPTION = other.JOB_DESCRIPTION;
//...same for the other fields
}
Once you have the constructor, you can clone the object by doing:
var NewJob = new Job(OldJob);

How to create a "pointer-like" class, easily exposing functions of member?

What I am trying to do is find the most elegant way to create a "pointer-like" class for a specific object/class type that I have in a project.
What I mean is a little confusing without an example. Take this really simple class:
public class MyClass
{
private string _name;
public string GetName() { return _name; }
public void SetName(string name) { _name = name; }
}
I want to create a second class which is like a pointer to it like this:
public class MyClassPtr
{
private MyClass _obj;
public bool IsValid = false;
public MyClassPtr(MyClass obj) { _obj = obj; IsValid = true; }
public void InvalidatePtr()
{
IsValid = false;
obj = null;
}
// SOME MAGIC HERE?
}
The challenge: The key is that I want to elegantly have MyClassPtr provide an interface to all of the public methods/members in MyClass without writing wrappers and/or accessors around each method/member.
I know that I could do this:
public class MyClassPtr
{
public string GetName() { return _obj.GetName(); }
...
}
But that's what I want to avoid. Is there some fundamental abstraction that I don't know of that I can apply to MyClassPtr to allow it to easily re-expose the methods/members in MyClass directed through _obj? I do NOT want MyClassPtr to inherit MyClass. Should MyClassPtr be a type instead, and some trick with accessors to expose the methods/members of MyClass?
Edit: More context on why I am looking for such a design through an example. Here is the overall goal. Imagine a platform that parses through data about people and when it finds information about a person, it creates an instance of Person with that information. You could get a handle to that person like:
Person person1 = platform.GetPerson(based_on_data);
Now, imagine the platform had two instances of Person that it thought were different people, but all of a sudden information came in that strongly suggested those two instances actually refer to the same person. So, the platform wants to merge the instances together in to a new object, let's call it personX.
Now, floating around in the platform someone had a copy of one of those two instances that got merged, which was person1. What I want to do is on-the-fly replace person1 with personX. Literally, I want person1==personX to be true, NOT just that they are two different objects with the same data. This is important since the platform could make a change to personX and unless the two objects are literally equal, a change to personX would not be automatically reflected in person1.
Since I can't on-the-fly replace person1 with personX I had that idea that I wouldn't give direct access to Person, instead I would give access to PersonPtr which the platform (on-the-fly) can change what Person it is pointing to. This would insurance that once person1ptr gets updated to point to personX, if a change is made in personX it will be seen in person1ptr
You could of course use something like
public class MyClassWrapper
{
MyClass _obj;
public MyClassWrapper(MyClass obj)
{
_obj = obj;
}
public void Invoke(Action<MyClass> action)
{
action(_obj);
}
public U Invoke<U>(Func<MyClass, U> func)
{
return func(_obj);
}
public void ChangeTo(MyClass obj)
{
_obj = obj;
}
}
Given your class looks like
public class MyClass
{
public string Name { get; set; }
}
Example:
var person1 = new MyClass { Name = "Instance1" };
var person2 = new MyClass { Name = "Instance2" };
var wrapper = new MyClassWrapper(person1);
wrapper.Invoke(x => x.Name += "original");
var x = wrapper.Invoke(x => x.Name); // Instance1original
wrapper.ChangeTo(person2);
var y = wrapper.Invoke(x => x.Name); // Instance2
but it has a major drawback: you can't access members directly, so you can't bind the data (to a DataTable or a Control).
It would be better to implement all members of your class also in your wrapper class. If you're afraid changes in your class will be forgotten to be implemented in your wrapper, just use an interface:
public interface IMyClass
{
string Name { get; set; }
}
public class MyClass : IMyClass
{
public string Name { get; set; }
}
public class MyClassWrapper: IMyClass
{
MyClass _obj;
public MyClassWrapper(MyClass obj)
{
_obj = obj;
}
public string Name
{
get { return _obj.Name; }
set { _obj.Name = value; }
}
}
Note that regardless which approach you use, you'll have to always keep a reference to the wrapper instance to actually change the underlying instance (using something like static aside).
Also, changing the underlying instance of such a wrapper without telling the component using it that it changed don't seem to be a good idea. Maybe your system is simple enough to get away with a wrapper; that's something you have to decide for yourself.
Maybe your wrapper should simply have an Invalid flag (and/or use an event to signal a change of the underlying object.). Once the underlying object is merged, it is set to true and each member access should throw an exception. This would force the component using the wrapper to deliberately react to changes and to reload the data from your service.
All in all, I think using such a wrapper will just clutter up your code and be error prone (just imagine adding multithreading to the mix). Think twice if you really need this wrapper.
Why not just simply ask your service for a new instance of your class everytime you use it (the service can simply use a cache)? Sure, you can't prevent that someone somewhere keeps a reference; but at least you'll keep your sanity.

How to pass data between function calls

We can pass data between functions by using class objects. Like i have class
public class AddsBean
{
public long addId{get;set;}
public int bid { get; set; }
public long pointsAlloted { get; set; }
public string userId { get; set; }
public enum isApproved { YES, NO };
public DateTime approveDate { get; set; }
public string title { get; set; }
public string description { get; set; }
public string Link { get; set; }
public DateTime dateAdded { get; set; }
}
We can call function like public List<AddsBean> getAdds(string Id). This approach is good when you need all the variables of class. But what if you need only 2 or 3 variables of class?
Passing object of class is not good because it will be wastage of memory. Another possible solution is to make different classes of lesser variables but that is not practical.
What should we do that will best possible solution to fulfill motive and best according to performance also?
In Java - "References to objects are passed by value".. So, you dont pass the entire object, you just pass the reference to the object to the called function.
EG:
class A{
int i;
int j;
double k;
}
class B{
public static void someFunc(A a) // here 'a' is a reference to an object, we dont pass the object.
{
// some code
}
public static void main(String[] args){
A a = new A();
B.someFunc(a); // reference is being passed by value
}
}
first of all, as Java is pass by value and references typed, there is no need to worry about the memory wastage.
next, as you have mentioned, it is not good to pass all the object if you do not need them all, in some situation, it's true. as you need to protect your data in instance, thus you can use different granularity of class, for instance:
class A
{id, name}
class B extends A
{password,birthday}
by refer to different class you can control the granularity yourself, and provide different client with different scope of data.
But in some condition, you need to use a instance to store all data in the whole application, like configure data in hadoop, or some other configuration related instance.
Try to choose the most suitable scope!
If you're sure that this is the source of problems and you don't want to define a new class with a subset of the properties, .NET provides the Tuple class for grouping a small number of related fields. For example, a Tuple<int, int, string> contains two integers and a string, in that order.
public Tuple<string, long, DateTime> GetPointsData()
{
AddsBean bean = ... // Get your AddsBean somehow
return Tuple.Create<string, long, DateTime>(bean.userId, bean.pointsAlloted, bean.approveDate);
}
Once this method goes out of scope, there is no longer a live reference to the object bean referred to and will be collected by the garbage collector at some point in the future.
That said, unless you're sure that instances of the AddsBean class are having a noticeable negative effect on the performance of your app, you should not worry about it. The performance of your application is probably affected far more by other operations. Returning a reference type (a type defined with class instead of struct) only passes a reference to the object, not the data of the object itself.

Generic Lists in a HttpSessionState stored in SQL

I'm working on a aspx application (C#), where I'm using HttpSessionState to save different objects in code behind between view changes. Some of these objects containts generic lists (List<T>), but those lists doesn't seem to be saved when I'm using an SQL database to store the state (sessionState mode = "SQLServer"). All other properties in the object gets saved, but when I try to retrieve the list, I get empty lists.
The funny thing is that it all works fine if I use sessionState mode = "InProc".
My classes have the Serializable attribute. I'm running C#/.NET 4.0.
Any ideas would be appreciated!
EDIT:
Just to clarify with some code (not verbatim!).
I have the classes I want to save (instances of) to my Session State:
public class MyClass
{
public string Property1 { get; set; }
public string Property2 { get; set; }
public List<MyOtherClass> Property3 { get; set; }
}
public class MyOtherClass
{
public string AnotherProperty1 { get; set; }
public string AnotherProperty2 { get; set; }
}
Then, in my Code Behind - one action saves objects of the previous classes:
public void MyMethod()
{
MyClass myClass = new MyClass()
{
Property1 = "One string",
Property2 = "One other string",
Property3 = new List<MyOtherClass>() { new MyOtherClass() { AnotherProperty1 = "One", AnotherProperty2 = "Ohter" } }
};
HttpContext.Current.Session["MyKey"] = myClass;
}
...and another action will retrieve that object:
public void MyOtherMethod()
{
MyClass myClass = (MyClass)HttpContext.Current.Session["MyKey"];
int c = myClass.Property3.Count; // Will be 0!!
}
So myClass.Property1 and myClass.Property2 will hold the strings I set previously, but myClass.Property3 is an empty list.
The problem you are describing could happen if you
Store a reference to an object in that generic list that is valid when you store it, but
the reference is no longer valid on subsequent requests.
An example would be storing a reference to a control from the Page.Controls collection - this reference would not be valid if you try to retrieve it on another postback. In fact, the reference may just be cleaned up by garbage collection (thus why your list appears to be empty).
Without seeing your actual code, it's tough to say for sure (although your example code does a great job of clarifying what you mean). But this seems likely to me.

Categories

Resources