Is this call-by-reference? - c#

I have an ArrayList:
ArrayList ReceivedPackets = new ArrayList();
And I have another ArrayList:
ArrayList returnList = ReceivedPackets;
Why does returnList loose it's value when I run this code?
ArrayList ReceivedPackets = new ArrayList(); // ReceivedPackets is empty
ReceivedPackets.Add(1); // Now it has an Integer
ArrayList returnList = ReceivedPackets; // Call-by-Reference (I thought), returnList now has an Integer
ReceivedPackets.clear(); // returnList is empty now. Why?

When you do this:
ArrayList returnList = ReceivedPackets;
You are creating a new variable called returnList, but this variable points to the same in-memory object as ReceivedPackets. There is still only one actual ArrayList, it just has two variables pointing to it. So changes made to one are reflected in both.
How can I do without returnList loosing it's value?
Create a new object. At its simplest, that would look like this:
ArrayList returnList = new ArrayList();
If you also want that object to contain all the values from ReceivedPackets, fortunately ArrayList has a constructor overload which does just that:
ArrayList returnList = new ArrayList(ReceivedPackets);
Now you'd have two objects which should contain copies of the same data. Changes to one would not be reflected in the other.
In the absence of that constructor, ArrayList also has some CopyTo() methods which can be used to copy elements from one to the other. Failing that, you could also manually loop over the source ArrayList and copy elements to the destination ArrayList.
It's possible that this can get pretty confusing if the ArrayList itself contains reference objects. Because those too may have multiple "pointers" to the same in-memory object.
For example, if you create a single Widget object and add it to two ArrayList objects, then any modifications made to the ArrayList objects (adding/removing elements) would be independent, but any modification made to the Widget object would be reflected in both ArrayLists.
The point is that the ArrayList itself is an object, independent of the objects it contains.
So, depending on the full context of what you're doing, your mileage may vary.

ArrayList is a reference type, meaning that if you simply assign some variable to an instance of it, both objects will point to the same location in memory.
If you want to create deep copy, create a new object.
static void Main() {
ArrayList a = new ArrayList() {1,2,3};
var b = a;
var c = new ArrayList(a);
a.Clear();
Console.WriteLine(a.Count); // 0
Console.WriteLine(b.Count); // 0
Console.WriteLine(c.Count); // 3
}

Related

create exact duplicate of a list of strings

Can I create an exact duplicate of a list in c#?
List<string> addedAttachments = new List<string>();
addedAttachments = (List<string>)HttpContext.Current.Session["UserFeedbackImage"];
List<string> tempList = addedAttachments;
Stores tempList in a different order
Thanks
You only assign the reference of your first list addadAttachments to a new variable, but don't create a new list.
To create a new list simply call
List<string> tempList = new List<string>(addedAttachments);
The order of the strings in the lists stays the same.
But note that this is only appropriate for immutable types like string. With a list of complex mutable objects, you would add the same objects to the new list, so if you change properties of an object in the old list, the "object in the new list" is also changed (it is the changed object). So you might also need to copy the objects.
To create a copy, try Linq:
List<string> tempList = addedAttachments.ToList();
Since you have a List<string> and string is immutable you can do:
List<string> tempList = addedAttachments.ToList();
If you have a custom object in your list then you should look for cloning.

Difference between List values = new ArrayList(); is better then ArrayList values = new ArrayList();?

Run into term Anti-patterns in programming, and one of examples was this.
IList values = new ArrayList(); //Anti-pattern, bad
ArrayList values = new ArrayList(); //good
What is the difference between this two variants? Aren't they the same, same as with using var keyword?
I assume by List you really mean IList.
IList values = new ArrayList(); just lets you view the ArrayList object as an IList object. You could cast back to ArrayList if you wanted.
ArrayList values = new ArrayList() is the same as var values = new ArrayList()
Neither is really an anti-pattern. If all you need is the methods that IList provides, it's considered good practice to only declare the type of object you need to use, regardless of what you assign it. This is more important in the public interface of a type. As a local variable; it doesn't really matter either way.
In this isolation, it is mostly irrelevant.
List values = new ArrayList();
ArrayList values = new ArrayList();
var values = new ArrayList();
because here, values is declared inside a method body, and we do not care much about abstraction or isolation.
But I agree, that assigning to a List just puts a restriction to the use of values that has no advantage. One might say, this is an AnitPattern, but there are much more relevant AntiPatterns.
ArrayList and var are better, var will most often be most readable and maintainable. I personally would use var.
As an aside, hardly anyone uses these collections anymore, ArrayList is sometimes prefered to List, but I personally use the latter also here.
The advantage with IList is there are many different classes that can be assigned to it. This can be handy if you're sourcing data from different places that use different classes.
IList values;
values = new ArrayList();
values = new object[] {};
values = new List<int>();
values = new DataView();
However, if you use an IList, you can only use the methods defined by an IList. If you define the variable as an ArrayList or any other concrete class, you have access to all of that class's methods.
ArrayList values = new ArrayList();
values.
Using the var keyword will tell the compiler to use the same class as the result of the expression. It can be very useful if you have a very long-winded class.
var values = new ArrayList();
// values is ArrayList
// Assuming a function: List<int> GetIntegerList() { ... }
var values = GetIntegerList();
// values is List<int>
// Assuming a function: Dictionary<string, Dictionary<string, List<Tuple<int, int, string>>>> GetSettingsCollection() { ... }
var values = GetSettingsCollection();
// values is Dictionary<string, Dictionary<string, List<Tuple<int, int, string>>>>

Accessing array element inside ArrayList c#

I have the following problem,
When i am trying to access data from an Array inside another Array List, it dispalys that "cannot apply indexing[] with to an expression of type 'object'".
This is my code
public void getWaypoints() {
ArrayList potentialWPs = new ArrayList();
potentialWPs.Add(containerWaypoint.GetComponentInChildren(typeof(Transform)));
wayPoints = new ArrayList();
foreach (Transform potentialWP in potentialWPs){
if(potentialWP.transform != containerWaypoint.transform){
wayPoints[wayPoints.Count] = new ArrayList(2);
wayPoints[wayPoints.Count][0] = potentialWP;
}
}
The error are shown in the line "wayPoints[wayPoints.Count][0]".
Any one have any idea why this error is occurred?
Since ArrayList is a non-generic collection class, all items retrieved from it are objects, and need to be cast to their real types, like this:
foreach (Transform potentialWP in potentialWPs){
if(potentialWP.transform != containerWaypoint.transform){
wayPoints[wayPoints.Count] = new ArrayList(2);
ArrayList arr = wayPoints[wayPoint.Count] as ArrayList; <-- THIS
arr[0] = potentialWP;
}
Several important things to note:
1) This would have been simpelr if you had simply created the new array and held a reference to it (the arr variable I introduced) and then used that to add to the wayPoints and to assign to.
2) ArrayList really is an old and primitve class. Is there a reason you don't use a List<Transform> instead>?
3) You have a bug in your code, since you're access the ArayList in position Count. An ArrayList of length 2, if accessed at position 2, will crash - ArrayLists are 0-based, so you need to use Count - 1 to access the last position (1) on a length 2 array.
Try this wayPoints[0] = potentialWP;
Since you have already declared an array list with size wayPoints.Count , you have to mention the index correctly.
An ArrayList only holds object types; that why you get
"cannot apply indexing[] with to an expression of type 'object'"
You need to cast
wayPoints
to your desired type
EDIT:
You should be using
List<T> (System.Collections.Generics)
wayPoints[wayPoints.Count] = new ArrayList(2);
wayPoints[wayPoints.Count][0] = potentialWP;
wayPoints[wayPoints.Count] returns an object. You need to cast it, before treating it like an ArrayList:
((ArrayList)wayPoints[wayPoints.Count])[0] = potentialWP;
However, you shouldn't use ArrayList, as it's deprecated. Use List instead.
The main problem you have is that by using ArrayList which is just a collection of objects, there is no implicit conversion to an array. As others have answered, one way is to cast the result to an array, after which you can access it by index.
A better way, might be to use a Generic List<T> which can be defined as a list of lists:
List<List<Transform>> waypoints = new List<List<Transform>>();
This would make your code a lot easier:
public void getWaypoints() {
ArrayList potentialWPs = new ArrayList();
potentialWPs.Add(containerWaypoint.GetComponentInChildren(typeof(Transform)));
List<Transform[]> waypoints = new List<Transform[]>();
foreach (Transform potentialWP in potentialWPs){
if(potentialWP.transform != containerWaypoint.transform){
wayPoints.Add( new List<Transform>>(){ potentialWP });
}
}
}
waypoints is now a "multi-dimensional" list of lists of Transform. You can access any element like so
List<Transform> first = waypoints[0];
or you could access a Transform directly
Transform firstOfFirst = waypoints[0][0];
or you could add another Transform to an existing list
waypoints[0].Add(anotherTransform);

An object in heap riddle

In the code below ViewState["L"] stores a List<string>. I create a new instance of List and assign the casted value of a viewstate to it.
List<string> myList = new List<string>();
myList=(List<string>)ViewState["L"];
Response.Write(myList.Equals(ViewState["L"]));// returns True
As you can see, .Equals() method tells me that the Viewstate object and the List object are the same.
Now my question to you guys is how can a List and a Viewstate be a reference to the same object? What does the heap memory at that location actually hold?
Update
The code below demonstrates that any variable that gets assigned a cast value of the viewstate, are all pointing to the same object.
List<string> myList1 = new List<string>();
myList1.Add("apple");
ViewState["L"] = myList1;
List<string> myList2 = new List<string>();
myList2 = (List<string>)ViewState["L"];
List<string> myList3 = new List<string>();
myList3 = (List<string>)ViewState["L"];;
myList3.Add("orange");//Here myList2 gets an orange too !
I think, Thomas is right.
how can a List and a Viewstate be a reference to the same object?
It's not "a ViewState", but an element of the ViewState. ViewState["L"] returns an object which is actually a List<string> (the same one you just assigned to myList)
I suppose you're talking about ASP.NET here.
Consider that ViewState is available on server side, before being trasmitted on client, you reference the exact same object allocated on heap on the server.
Hope this helps.
ViewState is actually an object of type StateBag
StateBag is just a container of other objects.
the ["L"] in ViewState["L"] is an indexer into ViewState that returns some object. In this case that object is a List<string> object
Your Equals() comparison is saying that the reference held by ViewState["L"] is equal to the reference held by myList
Hope that helps
You should read on value/reference types and operator precedence http://msdn.microsoft.com/en-us/library/6a71f45d.aspx.
List<string> myList = new List<string>();
Now previous value of myList is gone and replaced by (ViewState["L"]) cast to List<string>:
myList=(List<string>)ViewState["L"];
Now you compare 2 references to Object type (as the only suitable override is Object.Equals(Object) ) one myList (which holds (ViewState["L"]) ) and another (ViewState["L"]) itself. As result you get true for comparison.
Response.Write(myList.Equals(ViewState["L"]));// returns True

C#: When adding the same object to two List<object> variables, is the object cloned in the process?

I have something similar to this:
// Declarations:
List<SomeType> list1 = new List<SomeType>();
List<SomeType> list2 = new List<SomeType>();
...
SomeType something = new SomeType("SomeName");
list1.Add(something);
list2.Add(something);
...
list1[indexOfSomething] = new SomeType("SomeOtherName");
And the object in list2 isn't changed... Is that the expected result?
Yes, but nothing's cloned. Before the assignment, the same object is in both lists. After the assignment, you have two unique objects in two lists.
Do This:
list1[indexOfSomething].name = "SomeOtherName";
and the object in list2 will change, too.
// Declarations:
List<SomeType> list1 = new List<SomeType>();
List<SomeType> list2 = new List<SomeType>();
...
SomeType something = new SomeType("SomeName");
list1.Add(something);
list2.Add(something);
Remember, when you add an object to a list, you're really just adding a pointer to the object. In this case, list1 and list2 both point to the same address in memory.
list1[indexOfSomething] = new SomeType("SomeOtherName");
Now you've assigned the element list1 to a different pointer.
You're not really cloning objects themselves, you're copying the pointers which just happen to be pointing at the same object. If you need proof, do the following:
SomeType something = new SomeType("SomeName");
list1.Add(something);
list2.Add(something);
list1[someIndex].SomeProperty = "Kitty";
bool areEqual = list1[someIndex].SomeProperty == list2[someIndex].SomeProperty;
areEqual should be true. Pointers rock!
You are not cloning the object; you are adding a reference to the same object in the two lists. However, your code replaces the reference in one of the lists with a reference to another object, so yes, this is the expected behaviour.
You're replacing the reference in one list with a reference to a new object. If you were to instead change a property of that object, you would see it changed in both places, since the reference would remain the same.
Yes, you're not cloning the object. The object is being added to both lists originally by reference, and then subsequently you're assigned a reference in the list to the new object you're creating.
That is definitely the expected result.
When you pass the 'something' object to Add you are passing by value (c# default), not by reference
Yes that is expected. Only the reference to the object is added. Not the reference itself or a copy.

Categories