Say for example I have:

List<string> itemset1 = new List<string>();
List<string> itemset2 = new List<string>();
// Linkedlist itemsetcurrent

Which is declared outside the functions, and must be accessible from all the functions.
Now, I have a code like this:

private void SetList(List<string> list)
{
    itemsetcurrent = list
}

And:

private void ShowList()
{
    string x = listsetcurrent[0];
}

Basically, I want a link to a list (or other object), which can changed to another set, and will be updated when the list it is linked to changes, but without creating a duplicate list. (I hope this is a good enough explanation. Tell me if it isn't.)
Cheers,

Recommended Answers

All 9 Replies

Hi bbman,

It is a great question, and since C# is not explicit about references, there is some confusion about what exactly you are passing to a function.

Let's look at what happens when we pass a list to a function. There are generally two ways of doing this, and I will explain them both. Let's start with what you're doing in your example: passing without the "ref" keyword.

List<string> itemset1 = new List<string>();

Here, a reference (think of it as a GPS location of some data) is created to some string data. Let's call that reference itemset1_location.

SetList(itemset1);

// elsewhere...

      private void SetList(List<string> list)
      {
          itemsetcurrent = list
      }

What is happening here: our itemset1_location is copied to itemsetcurrent! So, a NEW reference is created, that points to the same place as our list. But the reference is actually different.

So if elsewhere I changed what itemset1 points to (by using the "new" keyword, for example), then my itemsetcurrent will still point to the old itemset1 data.

So if I did:

itemset1 = new List<string>();

and then inside ShowList(), I did

string x = listsetcurrent[0];

then the variable "x" is still pointing to the old itemset1 data, before the reference was changed.

To avoid this, use the "ref" keyword when passing your list to a function, for example:

private void SetList(ref List<string> list) { ...some code here... }

This way, your itemsetcurrent will always point to the same data as itemset1


Hope this helps!

Vasiliy Deych

To avoid this, use the "ref" keyword when passing your list to a function, for example:

private void SetList(ref List<string> list) { ...some code here... }

This way, your itemsetcurrent will always point to the same data as itemset1

Lists are reference types and are passed by reference by default.
Adding ref does not change the behaviour of SetList in the example.
When itemset1 is set to a new list; either a new instance or an existing instance
(e.g. itemset1 = new List<string>(); or itemset1 = itemset2; ) the same problem exists.

However, changes to the contents of the list are reflected in itemset1.

See the sample test code below. (The result is the same with or without ref)

List<string> list1;
        List<string> itemlist;

        private void button4_Click(object sender, EventArgs e)
        {
            // craete initial list1
            list1 = new List<string>();
            list1.Add("List 11111");

            // set itemlist to list1
            SetList(ref list1);
            
            // check value of itemlist
            Debug.WriteLine(itemlist[0]); // itemlist[0] is "List 11111"
            
            // change the data within list1
            list1.Clear();
            list1.Add("List 22222");

            // re-check value of item list
            Debug.WriteLine(itemlist[0]); // itemlist[0] is now "List 22222"

            // asign new value to list1
            list1 = new List<string>(); // or list1 = list2;
            list1.Add("List 33333");

            // re-check value of item list
            Debug.WriteLine(itemlist[0]); // itemlist[0] is STILL "List 22222"
            // list1 and itemlist now point to different list instances.
        }

        private void SetList(ref List<string> list)
        {
            itemlist = list;
        }

Hey,
Thanks for the replies, but I cannot do a ref in this case.
A function will be looking for the current list, and in reality, there is no "SetList" function.
But this may work, if I just link to a certain item in a list, and more is added, will it update? I need to be able to read and write to this item.
Cheers.

You can have as many variables as you like pointing to the same list. Changes made to the list using any one of them will be seen by all the other variables.
But be carefull of variables in different threads as simultaneous changes by different threads could cause problems. See below:

A List<(Of <(T>)>) can support multiple readers concurrently, as long as the collection is not modified. Enumerating through a collection is intrinsically not a thread-safe procedure. In the rare case where an enumeration contends with one or more write accesses, the only way to ensure thread safety is to lock the collection during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization.

Taken from MSDN List(Of T) Class

You can have as many variables as you like pointing to the same list. Changes made to the list using any one of them will be seen by all the other variables.
But be carefull of variables in different threads as simultaneous changes by different threads could cause problems. See below:

Taken from MSDN List(Of T) Class

So say I do this;

string str = List[0]; //"List item 0"
List.Add("Hello");
//Will str still be "list item 0"?
str = "Test";
//Will List[1] now = "Test"?

I did it a different method, which is also a lot better. Thanks for your help.

No. Your question is about the contents of the lists and not the lists themselves.
Lets look at the same question but using intergers.

int intval = intArray[0]; // 25
intArray[0] = 47;
//Will intval still be 25?  Yes
intval = 94;
//Will intArray[0] now = 94? No

The same is true for strings.

However, as I showed in my previous example you can have several references to the same list.
Try this code sample and see what get printed to the Debug window.

List<string> list1;
List<string> list2;
List<string> list3;

// create new list
list1 = new List<string>();
list1.Add("List 1 added this");
// assign list1 to list2 and list3
list2 = list1;
list3 = list1;

list2.Add("List 2 added this");
list3.Add("List 3 added this");

// check contents of list3
for (int i = 0; i < 3; i++)
{
    // write contents of list3 to debuger
    Debug.WriteLine(list3[i]);
}

Nick,

Thanks for the response. If I am wrong here, please correct me: using the "ref" keyword when passing reference types is not identical to passing without "ref".

The original question was:

I want a link to a list (or other object), which can changed to another set, and will be updated when the list it is linked to changes

It is correct to say that the list will be "updated when the list it is linked to changes" with or without the "ref" keyword. But consider the first part: "which can changed to another set". This means that, within SetList(), if we were to change the reference, the original reference will remain unchanged.

Example without "ref":

List<T> outsideList = new List<T>();

SetList(outsideList);

SetList(List<T> insideList)
{
// insideList and outsideList point to the same data
// however, the address of insideList data is stored in a different memory location than outsideList
insideList = new List<T>();  // insideList no longer points to the same data
insideList[0] = something; // outsideList is not affected by this assignment
}

Example with "ref":

List<T> outsideList = new List<T>();

SetList(ref outsideList);

SetList(ref List<T> insideList)
{
// insideList and outsideList point to the same data
// the addresses of insideList and outsideList are in the same memory location
insideList = new List<T>();  // outsideList now points to new data
insideList[0] = something; // outsideList[0] == something
}

[EDIT]
Just wanted to add my reasoning behind this. Again, correct me if I'm wrong. The reference to some object also needs to be stored somewhere. If we pass without "ref", then the reference is copied to a new location, which can be manipulated independently without affecting the original reference. When we pass with the ref keyword, we are specifying that we wish to manipulate the reference location oft he original reference...
[/EDIT]

Thanks,

Vasiliy Deych

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.