create exact duplicate of a list of strings - c#

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.

Related

If I reference List A to List B, I do changes on List B, would it affect List A?

I have a list called ListA: List<string> allStuffs = ...
I want to reference the list to ListB as List<string> secondList = allStuffs;
If I do something like secondList.Remove(someitem), would it also remove the same item on allStuffs?
Yes; there is only one list object in this example - whatever the ... is on the first line. The List<string> secondList = allStuffs; doesn't create a new list - it just creates a new reference, with the value copied from allStuffs - which is itself just a reference (not the list itself).
You can have as many references to that list object as you like: they're all just indicators as to where the actual list is.
So if you follow one copy of the reference to the object to call Remove, the change will be visible from any other reference to the same object.
Yes as explained in the above answer it is pointing to the same list. if you don't want to change the first list on change anything on the second then you can use it like this.
List<int> ls1 = new List<int>() { 1, 2, 3 };
List<int> ls2 = new List<int>(ls1);
ls2.Remove(1);
ls1 will still have 1,2 and 3

Why i have error result by use IList().toList().AddRange()?

Those are my old Code that cannot response correct result.
IList<string> testList=new List<string>();
testList.Add("string1");
var testList2=new List<string>(testList);
testList.ToList().AddRange(testList2);
I expect there are two elements in testList,but in fact it only have one;
If i change my to code to new style ,its can get the right result.Example :
IList<string> testList=new List<string>();
testList.Add("string1");
var testList2=new List<string>(testList);
var result=testList.ToList();
result.AddRange(testList2);
In result,it successfully have two elements.I guess the reason is iList().toList() create a new List in other place,as param result,that is independent from iList(). Is it right? or other reasons?
All the extension methods that come with System.Linq namespace create a new copy of the object (deep copy, if you will).
So, you are right when you say that a new list is created at another memory location.
To confirm whether two objects are different, you can get their memory addresses via unsafe and see for yourself. Here is something to test (be cautious if you are using unsafe code; you need to handle all the memory management yourself):
unsafe
{
IList<string> testList = new List<string>();
testList.Add("string1");
var testList2 = new List<string>(testList);
testList.ToList().AddRange(testList2);
TypedReference original = __makeref(testList);
IntPtr originalPointer = **(IntPtr**)(&original);
var isThisANewList = testList;
TypedReference newReferenceOnly = __makeref(testList);
IntPtr newReferenceOnlyPointer = **(IntPtr**)(&newReferenceOnly);
var copy = testList.ToList();
TypedReference deepCopy = __makeref(copy);
IntPtr deepCopyPointer = **(IntPtr**)(&deepCopy);
}
ToList() is an extension method that returns a list. You aren't holding that value in a variable, so although you call AddRange(), you are adding to the list you created in ToList() not to your testList.
In your second example, you are correctly holding the value of ToList() in result.
var result=testList.ToList();
result.AddRange(testList2);
You have a couple of options...
// option 1 declare testList as a List not IList
List<string> testList = new List<string>();
testList.AddRange(testList2);
// option 2 cast testList as a List
((List<string>)testList).AddRange(testList2);

Is this call-by-reference?

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
}

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>>>>

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