10

I noticed that the behavior of List<T> is different from an other simple object, say String for example. The question can seem newbie but that really struck me cause I thought that List<T> were simple objects.

Take for instance the following code:

List<String> ls1 = new List<String>();
ls1.Add("a");
List<String> ls2 = ls1;
ls1.Add("b");

At the end, ls1 will be equal to {"a", "b"} and so will ls2. This is really different from the behavior of this code:

String s1 = "a";
String s2 = s1;
s1 = "b";

Where s1 is at the end equal to b and s2 equal to a.

That means that List<T> is in fact a pointer right?

Otiel
  • 18,404
  • 16
  • 78
  • 126
  • 3
    They are called references, not pointers! – xanatos Oct 18 '11 at 13:39
  • `List` is an object, so yes, it is "like a pointer" (I use that term loosely since objects in managed code are not called "pointers", they're called references). – qJake Oct 18 '11 at 13:40
  • Yes, you are right. List<> is a reference type – sll Oct 18 '11 at 13:40
  • 5
    List and String are identical in this regard. The only reason you get different results is that you **do different things in those snippets**. Contrast `List ls1 = new List(); ls1.Add("a"); ls2 = ls1; ls2 = new List(); ls2.Add("b")`, which is much closer. Or to make it more obvious how that's the same as your string snippet, substitute collection initializers: `List ls1 = new List {"a"}; List ls2 = ls1; ls2 = new List {"b"};`. –  Oct 18 '11 at 13:41
  • 1
    How in the hell did this get so many up votes? It's not that interesting of a question, it's just a misunderstanding of how assignment works. – Roman Oct 18 '11 at 13:42
  • @R0MANARMY Today is the day of "what is a reference type"? There are various "similar" questions :-) For example this: http://stackoverflow.com/questions/7807765/breaking-c-sharp-references where I voted for close (pointing to a reply of Skeet) and Skeet wrote something very similar to what he had written the previous time :-) – xanatos Oct 18 '11 at 13:51
  • @xanatos: Well, I'm glad people are doing their own research before posting questions. – Roman Oct 18 '11 at 13:55
  • 1
    @R0MANARMY: In my question's defense, I'd say that vote up is not for _"interesting"_ questions but for _"useful and clear"_ questions. And I did do some research but found nothing conclusive because I had the wrong term for _reference_. Sorry I offended you with my _newbie_ question. :) – Otiel Oct 18 '11 at 14:09
  • @Leito: You didn't offend me. Knowing the right name for something can mean the difference between finding a good answer and confusing yourself further. In your case, knowing the difference between pointers and references (given that C# has both) would have helped you answer this question yourself. We were all beginners once, and I'm glad you got an answer to your question; however, its' still not **that** good of a question. – Roman Oct 18 '11 at 14:42

5 Answers5

7

List<T> a reference type, so yes it behaves like a pointer.

String is also a reference type, but strings are immutable and they behave like value types (contrast with reference types) in some cases hence your confusion here.

There is a good explanation of why string work this way here: In C#, why is String a reference type that behaves like a value type?

Community
  • 1
  • 1
Mike Mooney
  • 11,729
  • 3
  • 36
  • 42
3

The line s1 = "b" actually assigns a new reference to s1. s1 and s2 now refer to two different objects.

The changes to the List<string> object referred to by ls1 are visible through all references to that object, including ls2. When you make ls2 = ls1 you are basically saying that both ls1 and ls2 refer to the same object. Changes to the object via the reference variable ls1 are visible via the reference variable ls2.

Michael Goldshteyn
  • 71,784
  • 24
  • 131
  • 181
  • 2
    `The line s1 = "b" actually assigns a new reference to` - I believe it assign a new value rather than reference – sll Oct 18 '11 at 13:43
  • @sll, it assigns a reference to a new string which you can consider a value from the variable's perspective, because strings are reference types managed on the GC heap. See (http://www.yoda.arachsys.com/csharp/strings.html) for a good explanation. – Michael Goldshteyn Oct 18 '11 at 13:44
  • 1
    Well, it assigns a new value *to the variable*, although that value is a reference (as variables of reference types store references). –  Oct 18 '11 at 13:45
1

In C# they are called references, not pointers. Probably they are the same thing minus the fact that you can't cast them to an integer to print them and minus the pointer arithmetic that is forbidden. Technically they are "opaque", so you don't (shouldn't) know how they work. Clearly this opaqueness is broken if you use Managed C++ :-)

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • 2
    It is perhaps important to note that C# *can also* talk to pointers via `unsafe` code, hence yet another distinction between pointers and references. – Marc Gravell Oct 18 '11 at 13:44
  • 1
    @MarcGravell You can have two different concepts with the same word. In C++/Cli you have Managed Pointers and Pointers. But they are both named "pointers". It isn't the fact that C# supports unsafe coding that makes references "references" – xanatos Oct 18 '11 at 13:46
0

Every object in C# is a reference. Primitives like int, string, char, are not references.

xanatos
  • 109,618
  • 12
  • 197
  • 280
Stealth Rabbi
  • 10,156
  • 22
  • 100
  • 176
  • And it's not "primitive" which are not reference types, it's value types - that includes `struct`s. –  Oct 18 '11 at 13:50
  • I think it's confusing to call them objects. Value types inherit from `object` too. And there are types that are not primitives but are value types anyway, like `Guid`. – svick Oct 18 '11 at 13:50
  • also, "Every object in C# is a reference" ... well, not really - an object is an object; the *reference* is the... (scratches for a word) *reference* to the object, either on the working part of the stack, or in a field/local. – Marc Gravell Oct 18 '11 at 13:51
  • Of course, `IntPtr` is a value-type *and* a primitive (check `.IsPrimitive`), and is a *pointer* (related to, but different to, a reference)... kinda fun – Marc Gravell Oct 18 '11 at 13:52
0

String, int, float are all value types. So, when you say

String s1 = "a";
String s2 = s1;
s1 = "b";

When s2 is initialised, the value of s1 is copied into the space allocated to s2. So, if you were snooping on the memory, you could find the hex representation of "a" at two distinct locations in the memory(the location allocated to s1 and the memory allocated to s2). But if you try to do the same with a reference type, like List, what happens when you say something like this is a pass by reference:

List<String> ls1 = new List<String>();
ls1.Add("a");
List<String> ls2 = ls1;
ls1.Add("b");

is that have the object corresponding to the List allocated on the heap. The address of where to find this object resides on the space allocated for the local variables s1 and s2 instead of the actual value residing in that space. The reason is that the object(List) might be a large one and potentially long lived through the life of the program and it would be expensive to allocate memory off the stack for such an object. I recommend you read this question thread to understand more about how value types and reference types are really interpreted by the CLR

Community
  • 1
  • 1
gprasant
  • 15,589
  • 9
  • 43
  • 57
  • String is not value type. It behaves like value type, but it is immutable reference type. – Billy Nov 22 '14 at 04:15