ICollection.Clear remove data from copy object - c#

MyRequest copyRequest = new MyRequest();
copyRequest = request;
copyRequest.MyList.Clear();
I have above codes
MyList is a list of strings
When I call copyRequest.MyList.Clear()
it also clears request.MyList.
Is there any way to clear only copyRequest.MyList

This code:
MyRequest copyRequest = new MyRequest();
copyRequest = request;
...does not create a copy of request. It just reassigns the reference of request so it is one object with 2 aliases and the instance created with the new operator will be GCd as it has no references.
You need to implement IClonable which will then be responsible for creating a deep-copy of your MyRequest object, including the items of MyList.

By assigning the request to copyRequest both variables refer to the same objects. So if you then clear the list that affects to all variables referencing this object.
You have to create a new MyRequest and assign all related objects from the original request to the "copied". I assume the list is empty by default, so you don't need to assign and clear it.
MyRequest copyRequest = new MyRequest();
copyRequest.Property1 = request.Property1;
copyRequest.Property2 = request.Property2;
copyRequest.Property3 = request.Property3;
Since J. Skeet explains much better the difference of references and variables here's a quote:
One analogy I often use is of a house. Suppose we have two pieces of
paper (variables). The same house address is written on both pieces of
paper (that's the value of each variable, the reference). There's only
one house. If someone uses the first piece of paper to get to the
house, then paints the door red, they're not changing anything about
their piece of paper - they're changing something about the house.
Then if someone uses the second piece of paper to get to the house,
they'll see the front door is red too. There's only one house, however
many pieces of paper have its address written on them.
More detailed: http://jonskeet.uk/csharp/references.html

As others have pointed out, you're copying a reference, not the contents of MyList.
It's not clear what you're trying to achieve in the code, but it looks like what you want is a new MyRequest that is identical to the original except for the MyList, which you want to be emtpy. What you might want to do then is create a method that produces a new MyRequest without an empty MyList.
Bear in mind, though, that any reference in MyRequest will behave much the same way as MyList does. I.e., if Property1 is a reference type, the following
myResultCopy.Property1 = myResultOriginal.Property1
will result in myResultCopy.Property1 and myResultOriginal.Property1 referring to the same instance. So any change to myResultCopy.Property1 will be seen by users of myResultOriginal.Property1.

Related

Tell if an instance is pointed to by other variables?

This is a longshot but...
I understand there is a way to tell if variable A (var1, var2...., varX) points to instance of class by using Equals:
List<string> _mainInstance = new();
var var1 = _mainInstance;
var var2 = _mainInstance;
var var3 = _mainInstance;
//I understand how to tell if variable points to _mainInstance
if (var1.Equals(_mainInstance))
{
//It does because it points by reference
}
//I want to check if any variable still point to _mainInstance
if (!_mainInstance.HasOthersPointingToIt())
{
//Safe to delete _mainInstance
}
I don't know at design time how many pointers to _myInstance there will be. I want to check if my _mainInstance has any variables still pointing to it every so often. I thought maybe reflection or garbage collection but all my research there is coming up with nothing.
Is there a way to examine a variable (in this case an instance of a class) and tell if anything else (variables, properties of a class instance) still point to it?
Edit:
#GuruStron asks what is the underlying problem I am trying to solve?
Answer: I have a parent/child "tree" that I need to keep track of. That in itself is pretty easy. My difficulty is that the tree has blocks that have a single definition and that definition gets reused.
In the graph below it shows the top tree with stars. The stars represents pointers to block definitions. Below that on the left are the actual block definitions.
The the block definition gets substituted and the final tree looks like this:
When a block pointer is deleted I need to make sure that nothing else is pointing to that block definition and delete the block definition when it is no longer needed.

.Net Merge two identical objects, all properties, recursively when null

I have a task where I am provided a base object that contains objects and primitives from our dataservice, and couple it with data provided on an identical object that the client provides. It needs to end up being one complete object. I'll refer to the object as "MyObject".
Here is what the object looks like from the dataservice:
MyObject.FirstName = null
MyObject.LastName = null
MyObject.DataProperty1 = anotherobject
anotherobject.property1 = somevalue1
anotherobject.property2 = somevalue2
anotherobject.property2 = somevalue2
MyObject.DataProperty2 = yetanotherobject
yetanotherobject.property1 = someothervalue1
yetanotherobject.property2 = someothervalue2
yetanotherobject.property3 = someothervalue3
yetanotherobject.property4 = someothervalue4
Here is what the object looks like when provided by the client side
MyObject.FirstName = John
MyObject.LastName = Doe
MyObject.DataProperty1 = anotherobject
anotherobject.property1 = null
anotherobject.property2 = null
anotherobject.property2 = null
MyObject.DataProperty2 = yetanotherobject
yetanotherobject.property1 = null
yetanotherobject.property2 = null
yetanotherobject.property3 = null
yetanotherobject.property4 = null
I can't expect to know exactly which sub item objects will be null or not, but I do know that recursively, I need the final merged object to contain the actual data from both original objects, and not the nulls. Obviously the objects are going to be way more complicated that what i've typed above, but the gist is of my question is valid.
I've tried doing something like merging two objects in C# I couldn't figure out the non-primitives.
I really don't think this is a task for AutoMapper since the type of MyObject is the same class for both the client and the data side. It wouldn't make sense to map it to itself.
Too bad i cant just go
MyObject1 + MyObject2 = NewCombinedObject haha.
Also, this is legacy code and I realize its not 'best practice' at all. Still need to solve the problem though.
I can see two issues you will run into with this that are potential show-stoppers: nested object references and children that refer to their parents. Both can lead to infinite recursion scenarios and out of memory errors.
You can mitigate the nesting issue by simply deciding you won't merge any deeper than, say, x levels deep. It's not ideal, but it can prevent infinite recursion for that scenario.
The issue with children referring to their parents is more complex. You have to be able to map merged objects to their originals and then, in your output, map the referring node back to the one you've already merged. This is not a task for the faint of heart.
Is this a task that AutoMapper can't do for you? If it is, my gut tells me that it will do this for you far better than you can reinvent it, and with a greatly reduced risk of errors.

Stack of generic list gets cleared when pushed list is cleared

I have a little problem when i want to do some operations in c#. I will give you a little example.
Stack<List<HufmannLetter>> steps = new Stack<List<HufmannLetter>>();
List<HufmannLetter> letterList = new List<HufmannLetter>();
while(true){
letterList.Add("asd");
letterList.Add("sad");
steps.Push(letterList);
letterlist.Clear();
}
In this code, I want to push my linkedlist to a stack than remove all the items in the list. When I clear the list, my stack's first index disappears because it passed by reference. Am i wrong? Because I dont know why it happens.
So I use pass by value method.
Stack<List<HufmannLetter>> steps = new Stack<List<HufmannLetter>>();
List<HufmannLetter> letterList = new List<HufmannLetter>();
while(true) {
letterList.Add("asd");
letterList.Add("sad");
List<HufmannLetter> tempLetterList = new List<HufmannLetter>(letterList);
steps.Push(tempLetterList);
letterlist.Clear();
}
Is it a good way to solve a problem? This way it is working, but readability decreases. What do you suggest me?
Thanks...
Just create a new List<HufmannLetter> object inside the loop and add that to the stack. Reusing the same list object won't have any performance benefits.
Stack<List<HufmannLetter>> steps = new Stack<List<HufmannLetter>>();
while(true)
{
List<HufmannLetter> letterList = new List<HufmannLetter>();
letterList.Add("asd");
letterList.Add("sad");
steps.push(letterList);
}
You can create new List<HufmannLetter>() and give in the constructor the previous list, this will create new object which will be not cleared.
while(condition)
{
letterList.Add("asd");
letterList.Add("sad");
steps.push(new List<HufmannLetter>(letterList));
letterlist.Clear();
}
EDIT
So List<T> is reference type, you are putting the letterList in the stack. In this way you are transferring the value of the reference List<T> in the stack item. So your letterList variable reference the same object as the item in your stack. When you clear the items from letterList, they are cleared in the item of the stack too.
Check what is Reference Types
List<> is a mutable reference type.
When you pass a List<> to a method, you pass a copy of the reference. So you just tell which List<> it is. That will not copy (clone) the entire contents of the List<>.
When you put (Push) a List<> on the Stack<>, what the Stack<> really keeps is a copy of a reference to this instance of List<>. If that instance is later modified, for example with .Add("asd") or with .Clear(), this "mutation" will be seen whether you follow the reference kept by the Stack<> or another reference you have, from the local variable. Both references "point" to the same instance of List<>.
When, in your code, you say:
letterList.Clear(); // do not change reference, follow reference and mutate the instance it refers to
that will modify (mutate) the existing instance of List<> so it becomes empty. This change will be seen by anyone holding a reference to this particular instance of List<>.
If instead you had done:
letterList = new List<string>(); // create new instance, change reference to point there (reference assignment), old instance is unchanged
that would have "moved" the reference of letterList to point to a new instance of List<>. This would not affect people with other references to the "old" instance.
The title Pass By Reference Usage is misleading. It should have been Reference Types And Passing References or something like that.
you can also do that as
Stack<List<HufmannLetter>> steps = new Stack<List<HufmannLetter>>();
while(true)
{
var tempList = new List<HufmannLetter>;
tempList.add("asd");
steps.push(tempList);
}
or you can try this
steps.push(tempList.ToList());
tempList.Clear();

Diferences between object instantiation in C#: storing objects in references vs. calling a method directly

I have a doubt with the objects declarations in c#. I explain with this example
I can do this:
MyObject obj = New MyObject();
int a = obj.getInt();
Or I can do this
int a = new MyObject().getInt();
The result are the same, but, exists any diferences between this declarations? (without the syntax)
Thanks.
This isn't a declararation: it's a class instantiation.
There's no practical difference: it's all about readability and your own coding style.
I would add that there're few cases where you will need to declare reference to some object: when these objects are IDisposable.
For example:
// WRONG! Underlying stream may still be locked after reading to the end....
new StreamReader(...).ReadToEnd();
// OK! Store the whole instance in a reference so you can dispose it when you
// don't need it anymore.
using(StreamReader r = new StreamReader(...))
{
} // This will call r.Dispose() automatically
As some comment has added, there're a lot of edge cases where instantiating a class and storing the object in a reference (a variable) will be better/optimal, but about your simple sample, I believe the difference isn't enough and it's still a coding style/readability issue.
It's mostly syntax.
The main difference is that you can't use the instance of MyObject in the second example. Also, it may be nominated for Garbage Collection immediately.
No, technically they are the same.
The only thing I would suggest to consider in this case, as if the function does not actual need of instance creation, you may consider declare it static, so you can simply call it like:
int a = MyObject.getInt();
but this naturally depends on concrete implementation.

Understanding Lists of Objects

Was introduced to the concept of the generic List<>. Consider the following
// Create an instance of the Theater class.
this.MarcusTheater = new Theater();
// Set the field values of the Theater.
this.MarcusTheater.Screens = new List<Screen>();
this.MarcusTheater.Screen1 = new Screen();
// Set the field values for Screen1.
this.MarcusTheater.Screen1.Lenght = 23;
this.MarcusTheater.Screen1.Width = 50;
// Add Screen1 to the Screen list.
this.MarcusTheater.Screens.Add(this.MarcusTheater.Screen1);
From my understanding Screen1 is a temporary holder for the Screen instance. Once added to the list it becomes indexed within that list and isn't really Screen1? Since the instance of the Screen object is being stored within the Screen List, can I pull back this object in it's entirety? If so what is the best way to loop through a list<> of Screens in order to find Screen1? I know this might seem like a trivial question but I'm trying to nail down the basics. Thank you in advance.
From my understanding Screen1 is a temporary holder for the Screen
instance.
Kind of. It's is a "holder", but it's not temporary. Even when you add Screen1 to ScreenList, Screen1 is still valid. You've just copied the reference to that object. Figure this:
this.MarcusTheater = new Theater();
this.MarcusTheater.Screens = new List<Screen>();
this.MarcusTheater.Screen1 = new Screen();
// <your stuff here>
this.MarcusTheater.Screens.Add(this.MarcusTheater.Screen1);
Screen1 thisIsTheSameScreen = this.MarcusTheater.Screens[0];
At this point, this.MarcusTheater.Screen1 and thisIsTheSameScreen point to the same object. We're just passing its reference around.
So, if we did something like
thisIsTheSameScreen.Lenght = 20;
We would be changing for everyone, because it's the same object.
Once added to the list it becomes indexed within that list and isn't
really Screen1?
No. It's still the same, we are simply sharing the reference.
Since the instance of the Screen object is being stored within the
Screen List, can I pull back this object in it's entirety?
Sure, just like I did above.
If so what is the best way to loop through a list<> of Screens in
order to find Screen1?
You need a way to identify each screen, like an ID or a name. This way you can iterate that list and fetch the one you're looking for, either using Linq or a simple foreach.
I know this might seem like a trivial question but I'm trying to nail
down the basics. Thank you in advance.
And you're perfectly correct. We all should understand the tools we're using.
I would suggest that you think of class-type storage locations (fields, parameters, array elements, etc.) as holding "object IDs". The statement someScreen.Width = 123; doesn't change someScreen. If, before that statement executed, someScreen identified the 24,601st object that was created since the program started, the statement will ask object #24601 to set its Width property to 123, and leave someScreen referring to object #24601. If one says someList.Add(someScreen), and someList identifies the 8,675,309th object, then, then object #8675309 will be asked to add "object #24601" to itself. Note that the actual object #24601 will not be added to the list--merely its identity.
(I'm unaware of .NET providing a means by which one could determine which object was created between the 24,600th and 24,602nd objects, but if more than 24,602 objects have been created, exactly one such object must exist; during that run of the program, that object can never be anything other than the 24,601st object, nor can any other object ever be the 24,601st; if one accepts hypothetically that a particular object is the 24,601st one created, then "object #24601" may, within that hypothetical context, be used to refer to the object in question.)
Screens is not a temporary screen, it is the one and only instance. When you add it to the list a pointer or reference to screen 1 is made. If you were to modify screen 1 via either the instance or the list, both instances would change in step.
You should have a read about references, and possibly c++ pointers and that should help you understand.
Yes, the objects are reference types and therefore both variables will point to the same object in memory, there's a dead easy way to test this. You can use the Object.ReferencesEquals method to determine if they reference the same object.
Screen screen1 = new Screen();
screen1.Length = 23;
screen1.Width = 50;
Screen screen2 = new Screen();
screen2.Length = 23;
screen2.Width = 50;
List<Screen> screens = new List<Screen>();
screens.Add(screen1);
screens.Add(screen2);
Debug.WriteLine(Object.ReferenceEquals(screen1, screens[0])); // outputs true
Debug.WriteLine(Object.ReferenceEquals(screen2, screens[1])); // outputs true
Debug.WriteLine(Object.ReferenceEquals(screen1, screen2)); // outputs false

Categories