Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. Clever Code
  4. IList and Reference Types in C# [modified]

IList and Reference Types in C# [modified]

Scheduled Pinned Locked Moved Clever Code
helpcsharp
14 Posts 11 Posters 2 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    c2423
    wrote on last edited by
    #1

    I was working on some code earlier today and found what appears to be a bug in how IList is handled in C#... The following code seems to me to produce the wrong output:

    public void foo(IList listOfNumbers)
    {
    listOfNumbers = new List<int>();
    listOfNumbers.Add(1);
    listOfNumbers.Add(2);
    listOfNumbers.Add(3);
    }

    public void test()
    {
    IList listOfNumbers = new List<int>();
    listOfNumbers.Add(10);

    foo(listOfNumbers);
    
    MessageBox.Show(listOfNumbers\[0\].ToString());
    

    }

    Now I would expect that with IList being a reference type, when the call to foo is made, the reference to listOfNumbers is lost, and a new one is created. But it seems that the list keeps it's own reference as the message box shows "10" where I would have expected "1". Anyway, the fix I found was to use the ref keyword like so:

    public void foo(ref IList listOfNumbers)
    {
    listOfNumbers = new List<int>();
    listOfNumbers.Add(1);
    listOfNumbers.Add(2);
    listOfNumbers.Add(3);
    }

    public void test()
    {
    IList listOfNumbers = new List<int>();
    listOfNumbers.Add(10);

    foo(ref listOfNumbers);
    
    MessageBox.Show(listOfNumbers\[0\].ToString());
    

    }

    Here the result is now "1" which is what I had expected in both cases... I don't know why this is, but I'm guessing this is maybe compiler bug, or maybe there is some strangeness going on when you pass an interface, but I just thought I'd share this with you as it frustrated a couple of us for a few minutes today! Chris [Edit: I stand corrected! The compiler is producing the correct behaviour, as it passes the pointer by value - i.e. changes to the object would be kept (like List.Add), but changes to the pointer would not (i.e. referencing a new object). Thanks to everybody who pointed this out :) ]

    modified on Thursday, September 25, 2008 4:22 AM

    A P E M N 8 Replies Last reply
    0
    • C c2423

      I was working on some code earlier today and found what appears to be a bug in how IList is handled in C#... The following code seems to me to produce the wrong output:

      public void foo(IList listOfNumbers)
      {
      listOfNumbers = new List<int>();
      listOfNumbers.Add(1);
      listOfNumbers.Add(2);
      listOfNumbers.Add(3);
      }

      public void test()
      {
      IList listOfNumbers = new List<int>();
      listOfNumbers.Add(10);

      foo(listOfNumbers);
      
      MessageBox.Show(listOfNumbers\[0\].ToString());
      

      }

      Now I would expect that with IList being a reference type, when the call to foo is made, the reference to listOfNumbers is lost, and a new one is created. But it seems that the list keeps it's own reference as the message box shows "10" where I would have expected "1". Anyway, the fix I found was to use the ref keyword like so:

      public void foo(ref IList listOfNumbers)
      {
      listOfNumbers = new List<int>();
      listOfNumbers.Add(1);
      listOfNumbers.Add(2);
      listOfNumbers.Add(3);
      }

      public void test()
      {
      IList listOfNumbers = new List<int>();
      listOfNumbers.Add(10);

      foo(ref listOfNumbers);
      
      MessageBox.Show(listOfNumbers\[0\].ToString());
      

      }

      Here the result is now "1" which is what I had expected in both cases... I don't know why this is, but I'm guessing this is maybe compiler bug, or maybe there is some strangeness going on when you pass an interface, but I just thought I'd share this with you as it frustrated a couple of us for a few minutes today! Chris [Edit: I stand corrected! The compiler is producing the correct behaviour, as it passes the pointer by value - i.e. changes to the object would be kept (like List.Add), but changes to the pointer would not (i.e. referencing a new object). Thanks to everybody who pointed this out :) ]

      modified on Thursday, September 25, 2008 4:22 AM

      A Offline
      A Offline
      AWdrius
      wrote on last edited by
      #2

      Well, when you do not use the ref keyword you are basically copying reference to a function parameter variable instead of passing the actual reference to the object.

      Trust is a weakness.

      1 Reply Last reply
      0
      • C c2423

        I was working on some code earlier today and found what appears to be a bug in how IList is handled in C#... The following code seems to me to produce the wrong output:

        public void foo(IList listOfNumbers)
        {
        listOfNumbers = new List<int>();
        listOfNumbers.Add(1);
        listOfNumbers.Add(2);
        listOfNumbers.Add(3);
        }

        public void test()
        {
        IList listOfNumbers = new List<int>();
        listOfNumbers.Add(10);

        foo(listOfNumbers);
        
        MessageBox.Show(listOfNumbers\[0\].ToString());
        

        }

        Now I would expect that with IList being a reference type, when the call to foo is made, the reference to listOfNumbers is lost, and a new one is created. But it seems that the list keeps it's own reference as the message box shows "10" where I would have expected "1". Anyway, the fix I found was to use the ref keyword like so:

        public void foo(ref IList listOfNumbers)
        {
        listOfNumbers = new List<int>();
        listOfNumbers.Add(1);
        listOfNumbers.Add(2);
        listOfNumbers.Add(3);
        }

        public void test()
        {
        IList listOfNumbers = new List<int>();
        listOfNumbers.Add(10);

        foo(ref listOfNumbers);
        
        MessageBox.Show(listOfNumbers\[0\].ToString());
        

        }

        Here the result is now "1" which is what I had expected in both cases... I don't know why this is, but I'm guessing this is maybe compiler bug, or maybe there is some strangeness going on when you pass an interface, but I just thought I'd share this with you as it frustrated a couple of us for a few minutes today! Chris [Edit: I stand corrected! The compiler is producing the correct behaviour, as it passes the pointer by value - i.e. changes to the object would be kept (like List.Add), but changes to the pointer would not (i.e. referencing a new object). Thanks to everybody who pointed this out :) ]

        modified on Thursday, September 25, 2008 4:22 AM

        P Offline
        P Offline
        PIEBALDconsult
        wrote on last edited by
        #3

        Seems correct to me.

        1 Reply Last reply
        0
        • C c2423

          I was working on some code earlier today and found what appears to be a bug in how IList is handled in C#... The following code seems to me to produce the wrong output:

          public void foo(IList listOfNumbers)
          {
          listOfNumbers = new List<int>();
          listOfNumbers.Add(1);
          listOfNumbers.Add(2);
          listOfNumbers.Add(3);
          }

          public void test()
          {
          IList listOfNumbers = new List<int>();
          listOfNumbers.Add(10);

          foo(listOfNumbers);
          
          MessageBox.Show(listOfNumbers\[0\].ToString());
          

          }

          Now I would expect that with IList being a reference type, when the call to foo is made, the reference to listOfNumbers is lost, and a new one is created. But it seems that the list keeps it's own reference as the message box shows "10" where I would have expected "1". Anyway, the fix I found was to use the ref keyword like so:

          public void foo(ref IList listOfNumbers)
          {
          listOfNumbers = new List<int>();
          listOfNumbers.Add(1);
          listOfNumbers.Add(2);
          listOfNumbers.Add(3);
          }

          public void test()
          {
          IList listOfNumbers = new List<int>();
          listOfNumbers.Add(10);

          foo(ref listOfNumbers);
          
          MessageBox.Show(listOfNumbers\[0\].ToString());
          

          }

          Here the result is now "1" which is what I had expected in both cases... I don't know why this is, but I'm guessing this is maybe compiler bug, or maybe there is some strangeness going on when you pass an interface, but I just thought I'd share this with you as it frustrated a couple of us for a few minutes today! Chris [Edit: I stand corrected! The compiler is producing the correct behaviour, as it passes the pointer by value - i.e. changes to the object would be kept (like List.Add), but changes to the pointer would not (i.e. referencing a new object). Thanks to everybody who pointed this out :) ]

          modified on Thursday, September 25, 2008 4:22 AM

          E Offline
          E Offline
          Ennis Ray Lynch Jr
          wrote on last edited by
          #4

          The MS behavior is correct. When dealing with object parameters l-value and r-values seem to have strange behavior until you are used to it.

          Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
          Happiness in intelligent people is the rarest thing I know. -- Ernest Hemingway
          Most of this sig is for Google, not ego.

          1 Reply Last reply
          0
          • C c2423

            I was working on some code earlier today and found what appears to be a bug in how IList is handled in C#... The following code seems to me to produce the wrong output:

            public void foo(IList listOfNumbers)
            {
            listOfNumbers = new List<int>();
            listOfNumbers.Add(1);
            listOfNumbers.Add(2);
            listOfNumbers.Add(3);
            }

            public void test()
            {
            IList listOfNumbers = new List<int>();
            listOfNumbers.Add(10);

            foo(listOfNumbers);
            
            MessageBox.Show(listOfNumbers\[0\].ToString());
            

            }

            Now I would expect that with IList being a reference type, when the call to foo is made, the reference to listOfNumbers is lost, and a new one is created. But it seems that the list keeps it's own reference as the message box shows "10" where I would have expected "1". Anyway, the fix I found was to use the ref keyword like so:

            public void foo(ref IList listOfNumbers)
            {
            listOfNumbers = new List<int>();
            listOfNumbers.Add(1);
            listOfNumbers.Add(2);
            listOfNumbers.Add(3);
            }

            public void test()
            {
            IList listOfNumbers = new List<int>();
            listOfNumbers.Add(10);

            foo(ref listOfNumbers);
            
            MessageBox.Show(listOfNumbers\[0\].ToString());
            

            }

            Here the result is now "1" which is what I had expected in both cases... I don't know why this is, but I'm guessing this is maybe compiler bug, or maybe there is some strangeness going on when you pass an interface, but I just thought I'd share this with you as it frustrated a couple of us for a few minutes today! Chris [Edit: I stand corrected! The compiler is producing the correct behaviour, as it passes the pointer by value - i.e. changes to the object would be kept (like List.Add), but changes to the pointer would not (i.e. referencing a new object). Thanks to everybody who pointed this out :) ]

            modified on Thursday, September 25, 2008 4:22 AM

            M Offline
            M Offline
            mrLastro
            wrote on last edited by
            #5

            this is no bug! passing reference types by value, results in you beeing able to change their content but not to change the address of it in memory! so if you pass your list to foo and add some new elemts there, they will be added to the original list. but if you create a new list and assign it to your parameter, the only outcome will be, that you lose your connection to the passed reference! this behaivor is just like passing ponters and pointers to pointers in c++ but as you dont use pointers in c# (or at least you dont see the compiler using it :-) ) it's the only possibility to implement it. i hope this helps greets

            L 1 Reply Last reply
            0
            • M mrLastro

              this is no bug! passing reference types by value, results in you beeing able to change their content but not to change the address of it in memory! so if you pass your list to foo and add some new elemts there, they will be added to the original list. but if you create a new list and assign it to your parameter, the only outcome will be, that you lose your connection to the passed reference! this behaivor is just like passing ponters and pointers to pointers in c++ but as you dont use pointers in c# (or at least you dont see the compiler using it :-) ) it's the only possibility to implement it. i hope this helps greets

              L Offline
              L Offline
              Lost User
              wrote on last edited by
              #6

              I'm not sure I completely understand you - did you say C# can not use pointers? Pointers are available in C# if you use the "unsafe" keyword

              B 1 Reply Last reply
              0
              • C c2423

                I was working on some code earlier today and found what appears to be a bug in how IList is handled in C#... The following code seems to me to produce the wrong output:

                public void foo(IList listOfNumbers)
                {
                listOfNumbers = new List<int>();
                listOfNumbers.Add(1);
                listOfNumbers.Add(2);
                listOfNumbers.Add(3);
                }

                public void test()
                {
                IList listOfNumbers = new List<int>();
                listOfNumbers.Add(10);

                foo(listOfNumbers);
                
                MessageBox.Show(listOfNumbers\[0\].ToString());
                

                }

                Now I would expect that with IList being a reference type, when the call to foo is made, the reference to listOfNumbers is lost, and a new one is created. But it seems that the list keeps it's own reference as the message box shows "10" where I would have expected "1". Anyway, the fix I found was to use the ref keyword like so:

                public void foo(ref IList listOfNumbers)
                {
                listOfNumbers = new List<int>();
                listOfNumbers.Add(1);
                listOfNumbers.Add(2);
                listOfNumbers.Add(3);
                }

                public void test()
                {
                IList listOfNumbers = new List<int>();
                listOfNumbers.Add(10);

                foo(ref listOfNumbers);
                
                MessageBox.Show(listOfNumbers\[0\].ToString());
                

                }

                Here the result is now "1" which is what I had expected in both cases... I don't know why this is, but I'm guessing this is maybe compiler bug, or maybe there is some strangeness going on when you pass an interface, but I just thought I'd share this with you as it frustrated a couple of us for a few minutes today! Chris [Edit: I stand corrected! The compiler is producing the correct behaviour, as it passes the pointer by value - i.e. changes to the object would be kept (like List.Add), but changes to the pointer would not (i.e. referencing a new object). Thanks to everybody who pointed this out :) ]

                modified on Thursday, September 25, 2008 4:22 AM

                N Offline
                N Offline
                Nemanja Trifunovic
                wrote on last edited by
                #7

                c2423 wrote:

                Now I would expect that with IList being a reference type, when the call to foo is made, the reference to listOfNumbers is lost, and a new one is created.

                A reference type means that listOfNumbers is a reference to an unnamed object on the managed heap. If you make a change to the object itself, the change will be visible in the outer function. However, the reference itself is passed to the function by value, unless you use ref keyword, so within the function you have a copy of the original reference that points to the same object. If you change the object the reference is pointing to, the original reference will not be affected by it.

                Programming Blog utf8-cpp

                C 1 Reply Last reply
                0
                • N Nemanja Trifunovic

                  c2423 wrote:

                  Now I would expect that with IList being a reference type, when the call to foo is made, the reference to listOfNumbers is lost, and a new one is created.

                  A reference type means that listOfNumbers is a reference to an unnamed object on the managed heap. If you make a change to the object itself, the change will be visible in the outer function. However, the reference itself is passed to the function by value, unless you use ref keyword, so within the function you have a copy of the original reference that points to the same object. If you change the object the reference is pointing to, the original reference will not be affected by it.

                  Programming Blog utf8-cpp

                  C Offline
                  C Offline
                  c2423
                  wrote on last edited by
                  #8

                  Thanks, for me this was the clearest explanation given by anybody on this thread! Thanks, Chris

                  1 Reply Last reply
                  0
                  • C c2423

                    I was working on some code earlier today and found what appears to be a bug in how IList is handled in C#... The following code seems to me to produce the wrong output:

                    public void foo(IList listOfNumbers)
                    {
                    listOfNumbers = new List<int>();
                    listOfNumbers.Add(1);
                    listOfNumbers.Add(2);
                    listOfNumbers.Add(3);
                    }

                    public void test()
                    {
                    IList listOfNumbers = new List<int>();
                    listOfNumbers.Add(10);

                    foo(listOfNumbers);
                    
                    MessageBox.Show(listOfNumbers\[0\].ToString());
                    

                    }

                    Now I would expect that with IList being a reference type, when the call to foo is made, the reference to listOfNumbers is lost, and a new one is created. But it seems that the list keeps it's own reference as the message box shows "10" where I would have expected "1". Anyway, the fix I found was to use the ref keyword like so:

                    public void foo(ref IList listOfNumbers)
                    {
                    listOfNumbers = new List<int>();
                    listOfNumbers.Add(1);
                    listOfNumbers.Add(2);
                    listOfNumbers.Add(3);
                    }

                    public void test()
                    {
                    IList listOfNumbers = new List<int>();
                    listOfNumbers.Add(10);

                    foo(ref listOfNumbers);
                    
                    MessageBox.Show(listOfNumbers\[0\].ToString());
                    

                    }

                    Here the result is now "1" which is what I had expected in both cases... I don't know why this is, but I'm guessing this is maybe compiler bug, or maybe there is some strangeness going on when you pass an interface, but I just thought I'd share this with you as it frustrated a couple of us for a few minutes today! Chris [Edit: I stand corrected! The compiler is producing the correct behaviour, as it passes the pointer by value - i.e. changes to the object would be kept (like List.Add), but changes to the pointer would not (i.e. referencing a new object). Thanks to everybody who pointed this out :) ]

                    modified on Thursday, September 25, 2008 4:22 AM

                    S Offline
                    S Offline
                    steveb
                    wrote on last edited by
                    #9

                    Passing by value means passing a copy of whatever object. Passing by reference is passing physical object itself .

                    L 1 Reply Last reply
                    0
                    • S steveb

                      Passing by value means passing a copy of whatever object. Passing by reference is passing physical object itself .

                      L Offline
                      L Offline
                      Lost User
                      wrote on last edited by
                      #10

                      Hey I would like to suggest reading C# in depth. This will answer many of the questions you will have including this one in depth. I bought it and really enjoyed reading it. Give it a try :)

                      At university studying Software Engineering - if i say this line to girls i find they won't talk to me Dan

                      1 Reply Last reply
                      0
                      • L Lost User

                        I'm not sure I completely understand you - did you say C# can not use pointers? Pointers are available in C# if you use the "unsafe" keyword

                        B Offline
                        B Offline
                        BillW33
                        wrote on last edited by
                        #11

                        What he means is that in C# you don't use pointers to pass in a parameter by reference, instead you use the ref keyword. Under the hood it is still using a pointer. Bill W

                        Just because code works, it doesn't mean that it is good code.

                        L 1 Reply Last reply
                        0
                        • B BillW33

                          What he means is that in C# you don't use pointers to pass in a parameter by reference, instead you use the ref keyword. Under the hood it is still using a pointer. Bill W

                          Just because code works, it doesn't mean that it is good code.

                          L Offline
                          L Offline
                          Lost User
                          wrote on last edited by
                          #12

                          Why "do you not use pointers"? Sure it's ugly, but you Can use raw pointers, don't pretend that you can't That, was my point. edit: and what's with the 1 votes, look at this:

                          Goran Lastro wrote:

                          it's the only possibility to implement it

                          And then compare that to The Reality(tm) which is that you can use real pointers so it isn't the only way to implement it.

                          modified on Monday, October 20, 2008 1:50 PM

                          1 Reply Last reply
                          0
                          • C c2423

                            I was working on some code earlier today and found what appears to be a bug in how IList is handled in C#... The following code seems to me to produce the wrong output:

                            public void foo(IList listOfNumbers)
                            {
                            listOfNumbers = new List<int>();
                            listOfNumbers.Add(1);
                            listOfNumbers.Add(2);
                            listOfNumbers.Add(3);
                            }

                            public void test()
                            {
                            IList listOfNumbers = new List<int>();
                            listOfNumbers.Add(10);

                            foo(listOfNumbers);
                            
                            MessageBox.Show(listOfNumbers\[0\].ToString());
                            

                            }

                            Now I would expect that with IList being a reference type, when the call to foo is made, the reference to listOfNumbers is lost, and a new one is created. But it seems that the list keeps it's own reference as the message box shows "10" where I would have expected "1". Anyway, the fix I found was to use the ref keyword like so:

                            public void foo(ref IList listOfNumbers)
                            {
                            listOfNumbers = new List<int>();
                            listOfNumbers.Add(1);
                            listOfNumbers.Add(2);
                            listOfNumbers.Add(3);
                            }

                            public void test()
                            {
                            IList listOfNumbers = new List<int>();
                            listOfNumbers.Add(10);

                            foo(ref listOfNumbers);
                            
                            MessageBox.Show(listOfNumbers\[0\].ToString());
                            

                            }

                            Here the result is now "1" which is what I had expected in both cases... I don't know why this is, but I'm guessing this is maybe compiler bug, or maybe there is some strangeness going on when you pass an interface, but I just thought I'd share this with you as it frustrated a couple of us for a few minutes today! Chris [Edit: I stand corrected! The compiler is producing the correct behaviour, as it passes the pointer by value - i.e. changes to the object would be kept (like List.Add), but changes to the pointer would not (i.e. referencing a new object). Thanks to everybody who pointed this out :) ]

                            modified on Thursday, September 25, 2008 4:22 AM

                            H Offline
                            H Offline
                            hamityildirim
                            wrote on last edited by
                            #13

                            this is the normal behavior in the C# like to the ECMA I didnt understand why you crawled with.. ;P

                            1 Reply Last reply
                            0
                            • C c2423

                              I was working on some code earlier today and found what appears to be a bug in how IList is handled in C#... The following code seems to me to produce the wrong output:

                              public void foo(IList listOfNumbers)
                              {
                              listOfNumbers = new List<int>();
                              listOfNumbers.Add(1);
                              listOfNumbers.Add(2);
                              listOfNumbers.Add(3);
                              }

                              public void test()
                              {
                              IList listOfNumbers = new List<int>();
                              listOfNumbers.Add(10);

                              foo(listOfNumbers);
                              
                              MessageBox.Show(listOfNumbers\[0\].ToString());
                              

                              }

                              Now I would expect that with IList being a reference type, when the call to foo is made, the reference to listOfNumbers is lost, and a new one is created. But it seems that the list keeps it's own reference as the message box shows "10" where I would have expected "1". Anyway, the fix I found was to use the ref keyword like so:

                              public void foo(ref IList listOfNumbers)
                              {
                              listOfNumbers = new List<int>();
                              listOfNumbers.Add(1);
                              listOfNumbers.Add(2);
                              listOfNumbers.Add(3);
                              }

                              public void test()
                              {
                              IList listOfNumbers = new List<int>();
                              listOfNumbers.Add(10);

                              foo(ref listOfNumbers);
                              
                              MessageBox.Show(listOfNumbers\[0\].ToString());
                              

                              }

                              Here the result is now "1" which is what I had expected in both cases... I don't know why this is, but I'm guessing this is maybe compiler bug, or maybe there is some strangeness going on when you pass an interface, but I just thought I'd share this with you as it frustrated a couple of us for a few minutes today! Chris [Edit: I stand corrected! The compiler is producing the correct behaviour, as it passes the pointer by value - i.e. changes to the object would be kept (like List.Add), but changes to the pointer would not (i.e. referencing a new object). Thanks to everybody who pointed this out :) ]

                              modified on Thursday, September 25, 2008 4:22 AM

                              J Offline
                              J Offline
                              johannesnestler
                              wrote on last edited by
                              #14

                              :wtf: , - Read the docu about the ref-keyword! This is what I'd do before I post "strange behaviour/bug" here....

                              1 Reply Last reply
                              0
                              Reply
                              • Reply as topic
                              Log in to reply
                              • Oldest to Newest
                              • Newest to Oldest
                              • Most Votes


                              • Login

                              • Don't have an account? Register

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • World
                              • Users
                              • Groups