I wanted to know if i have few list obejcts in my code, if i want to declare all the lists in one line is it equal to declaration in seperate lines:
ListA = ListB = ListC ... = new List<MyType>();
is it equal to:
ListA = new List<MyType>();
ListB = new List<MyType>();
ListC = new List<MyType>();
...
I must be sure i will have no aliasing issue that way
as Flydog57 commented out, the assignment reffers to the same object in the 1st example,
and create new instance on the 2nd example.
Related
I cannot find an answer because it seems too much specific. So here's my issue with C#.
We can add another list to another one as a clone like this
list2 = new List<int>(list1);
What I want to know is how can I add a List into another one without any reference of the child?
List<List<List<int>>> wireCoords = new List<List<List<int>>>();
List<int> coord = new List<int>();
for(int i = 0; i < inputSplits.Length; i++)
{
coord.Add(0);
coord.Add(0);
wireCoords[i].Add(coord);
}
AS soon the wireCoords[0][0] list change, it also change inside wireCoords[1][0]
How can I fix this?
Two things. You cannot access a List via [i] accessor unless it has content at that index. Second, you can copy the values of a list by using List1.AddRange(List2). After this, changing List2 will not change List1.
In your for loop, the number of items grow to inputSplits.Length * 2 for every index of wiredCoords. To explain why this happens, lets take an example.
List<int> object1 = new List<int>();
object1.Add(1);
object1.Add(2);
List<int> object2 = object1;
object1.Add(3);
// at this time, object2 also has an element 3.
Console.WriteLine(string.Join(",", object2));
output:
1,2,3 (instead of 1,2 that you'd normally expect)
object1 never gets assigned the "value" of object2. object1 will get "reference" of the object2 and anywhere in code when you change values of object1, object2 will automatically get updated.
Fix for that could be
List<int> object2 = object1;
object1 = new List<int>(); // re-initialized
object1.Add(3);
// object1 has only 1 element
// object2 has 2 elements.
To resolve this, you create a new object or re-initialize the object to get a new reference and then use that for later assignments.
Your code:
List<List<List<int>>> wireCoords = new List<List<List<int>>>();
List<int> coord ;
for(int i = 0; i < inputSplits.Length; i++)
{
coord = new List<int>();
coord.Add(0);
coord.Add(0);
wireCoords.Add(coord);
}
Hope it helps.
Adding to extensive explanation of the issue by #Jawad, here is how you can do that with LINQ in more concise and functional way:
List<List<List<int>>> wireCoords = inputSplits
.Select(_=> new List<int>(){0,0})
.Select(coords=> new List<List<int>>(){coords})
.ToList();
EDIT:
To whoever marked the question as duplicate. That question is for how to create a deep copy. My question was how to make sure a the copy constructor is called when copying a list of class elements.
I'm trying to make a deep copy of a List that contain custom class elements. If I have a List of strings I can just use
List<string> secondList = new List<string>(firstList);
and then freely modify the elements in the second list without effeting the ones in the firwst list. But when I try to do the same with a custom class type both lists get changed. To try and solve it I made a small test program that just has this class.
class TestClass
{
public string name;
public TestClass(string n)
{
name = n;
}
public TestClass(TestClass original)
{
name = original.name;
}
}
And all my program does is this
TestClass t = new TestClass("Name1");
List<TestClass> list1 = new List<TestClass>();
list1.Add(t);
List<TestClass> list2 = new List<TestClass>(list1);
list2[0].name = "Name2";
That last line of code changes the name of the first element in both lists, which I do no want.
The issue here is that your objects are reference types, and the lists hold references to those objects.
This means that even though your second list has a COPY of the references from the first list, the references are still pointing to the original objects.
In order to solve this, you must clone not the references in the lists but instead the actual objects that you have stored in the lists.
You have already defined a copy constructor for your class, so you can use that to make a deep copy of the list as follows:
var list2 = list1.Select(item => new TestClass(item)).ToList();
You create a reference with this line of Code:
List<TestClass> list2 = new List<TestClass>(list1);
But you won't like to use Call-by-Reference. You Need Call-by-Value
in this Approach.
so the working code in lambda-expression is the following one:
TestClass t = new TestClass("Name1");
List<TestClass> list1 = new List<TestClass>();
list1.Add(t);
List<TestClass> list2 = new List<TestClass>();
list2 = list1.Select(item => new TestClass(item)).ToList();
list2[0].name = "Name2";
Have fun with it...
I just want to know the difference between List<string> lst = new List() and List<> lst = new List()
There is no List type. List<T> (or List(Of T) in VB) is a generic. It means that the list can only hold a type you pass in.
For instance:
List<string> list1 = new List<string>();
list1.Add("hello"); // OK
list1.Add(123); // Compiler error
List<int> list2 = new List<int>();
list2.Add("hello"); // Compiler error
list2.Add(123); // OK
You can read more about the generic list at MSDN.
If you want an un-typed list, you can use an ArrayList:
ArrayList list = new ArrayList();
list.Add("hello"); // OK
list.Add(123); // OK
But then you must know the type when you use an item from the list, since it can be any object.
I have a line of code like this:
List<string>[] apples = new List<string>()[2];
Its purpose is simply to create an array of List objects. When I try to compile my code, the above line generates this error:
Cannot implicitly convert type 'string' to 'System.Collections.Generic.List[]
I haven't been able to find much on the subject of creating an array of List objects (actually only this thread), maybe because no search engines will search for brackets.
Is the only way to create a collection of Lists to put them in another list, like below?
List<List<string>> apples = new List<List<string>>(); //I've tried this and it works as expected
Thanks for any suggestions, I'm really just curious as to why the first line of code (the List[] example) doesn't work.
You can do this. The syntax would be:
List<string>[] apples = new List<string>[2];
Note that this only allocates an array of references - you'll need to actually construct the individual list elements before you use them:
List<string>[] apples = new List<string>[2];
apples[0] = new List<string>();
apples[1] = new List<string>();
Alternatively, you can use the collection initialization syntax (works well for small numbers of fixed elements), ie:
List<string>[] apples = new[] { new List<string>(), new List<string>() };
Try this:
List<string>[] apples = new List<string>[2];
You do the initialization of each list afterwards:
apples[0] = new List<string>();
var listArray = new List<string>[2];
for (var i = 0; i < listArray.Length; i++)
{
listArray[i] = new List<string>();
}
How to cast two List...
I want something like that
List<Obj1> list = new List<Obj1>();
list.add(new Obj1);
List<Obj2> list2 = new List<Obj2>();
list2.add((Obj1)list[0]);
You may be interested in the Enumerable extension method Cast.
IEnumerable<Obj2> enumerable = list.Cast<Obj2>();
You can then convert to List if necessary:
var list2 = enumerable.ToList()
(This obviously assume the cast from Obj1 to Obj2 is valid: that Obj2 derives from Obj1 or that a conversion operator exists.)
I'm not sure what you are trying to do but it might be something like this
var nums = new List<int> {3,1,4,1,5,9,2,6,5};
var words = new List<string> {"Do", "not", "disturb", "my", "circles"};
words.AddRange(nums.Cast<string>());
To add a single element, your code would work, provided you fix the syntax:
List<Obj1> list = new List<Obj1>();
list.Add(new Obj1());
List<Obj2> list2 = new List<Obj2>();
list2.Add((Obj1)list[0]);
To concatenate the the whole list you can replace the last line with list2.AddRange(list.Cast<Obj1>());