C# – Passing By ref and out

cpass-by-reference

So if I am iterating using a foreach loop and I have a function inside that takes an argument of the object iterated from list, and lets say i set its value to be different.
Why don't I have to use out or ref ? I thought it was only passed by value if it you didn't use out or ref…. I know that a ref you must have initialized the variable before and out you just have to have set its value before return from the method.

It seems like if you a iterating thru a list and pass an object in its actually passed by reference. Consider the following example.

Example

class Program
    {
        static void Main(string[] args)
        {

            List<Foo> list = new List<Foo>();
            list.Add(new Foo() { Bar = "1" });
            list.Add(new Foo() { Bar = "2" });



            foreach (var f in list)
            {
                Foo f2 = f; 
                Console.WriteLine("SetFoo Pre: " + f2.Bar);
                SetFoo(f2);
                Console.WriteLine("SetFoo Post: " + f2.Bar);

                Console.WriteLine("SetFooRef Pre: " + f2.Bar);
                SetFooRef(ref f2);
                Console.WriteLine("SetFooRef Post: " + f2.Bar);
                Console.WriteLine("");
            }




            Console.WriteLine("");

            int i = 0;
            // Not using ref keyword
            Console.WriteLine("SetI Pre: " + i);
            SetI(i);
            Console.WriteLine("SetI Post: " + i);

            // Using ref keyword
            Console.WriteLine("SetRefI Pre: " + i);
            SetRefI(ref i);
            Console.WriteLine("SetRefI Post: " + i);
        }


        private static void SetRefI(ref int i)
        {
            i = 3;
            Console.WriteLine("SetRefI Inside: " + i);
        }

        private static void SetI(int i)
        {
            i = 2;
            Console.WriteLine("SetI Inside: " + i);
        }

        private static void SetFooRef(ref Foo f)
        {
            f.Bar = String.Format("{0} :: {1}", f.Bar, "WithRef");
            Console.WriteLine("SetFooRef Inside: " + f.Bar);
        }

        private static void SetFoo(Foo f)
        {
            f.Bar = String.Format("{0} :: {1}", f.Bar, "WithoutRef");
            Console.WriteLine("SetFoo Inside: " + f.Bar);
        }
    }


    class Foo
    {
        public string Bar { get; set; }
    }

Output:

SetFoo Pre: 1 SetFoo Inside: 1 ::
WithoutRef SetFoo Post: 1 WithoutRef
SetFoo Pre: 1 :: WithoutRef SetFoo
Inside: 1 :: WithoutRef :: WithRef
SetFoo Post: 1 WithoutRef :: WithRef

SetFoo Pre: 2 SetFoo Inside: 2 ::
WithoutRef SetFoo Post: 2 WithoutRef
SetFoo Pre: 2 :: WithoutRef SetFoo
Inside: 2 :: WithoutRef :: WithRef
SetFoo Post: 2 WithoutRef :: WithRef

SetI Pre: 0 SetI Inside: 2 SetIPost: 0

SetRefI Pre: 0 SetRefI Inside: 3
SetRefI Post: 3

I understand the ref with the integer example but not the above Foo object iteration example.

Thanks!

Best Answer

The reference is passed by value. So the method can still change the contents of the object, it just can't change which object your variable refers to.

See my article on parameter passing for a lot more information, along with my article about reference types and value types.