Передача по реф и вне - PullRequest
       9

Передача по реф и вне

1 голос
/ 29 октября 2009

Так что, если я выполняю итерацию, используя цикл foreach, и внутри меня есть функция, которая принимает аргумент объекта, повторяемого из списка, и, скажем, я устанавливаю его значение другим. Почему я не должен использовать или ref? Я думал, что он был передан по значению только в том случае, если вы не использовали out или ref .... Я знаю, что ref, вы, должно быть, инициализировали переменную до, и вы просто должны установить ее значение перед возвратом из метода.

Похоже, если вы перебираете список и передаете объект, фактически переданный по ссылке. Рассмотрим следующий пример.

Пример

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; }
    }

Выход:

SetFoo Pre: 1 SetFoo Inside: 1 ::
Без реферата SetFoo Сообщение: 1 Без реферата
SetFoo Pre: 1 :: WithoutRef SetFoo
Внутри: 1 :: WithoutRef :: WithRef
SetFoo Post: 1 WithoutRef :: WithRef

SetFoo Pre: 2 SetFoo Inside: 2 ::
Без реферата SetFoo Сообщение: 2 Без реферата
SetFoo Pre: 2 :: WithoutRef SetFoo
Внутри: 2 :: WithoutRef :: WithRef
SetFoo Post: 2 WithoutRef :: WithRef

SetI Pre: 0 SetI Inside: 2 SetIPost: 0

SetRefI Pre: 0 SetRefI Внутри: 3
SetRefI Post: 3

Я понимаю ссылку с целочисленным примером, но не с приведенным выше примером итерации объекта Foo.

Спасибо!

1 Ответ

12 голосов
/ 29 октября 2009

Ссылка передается по значению. Таким образом, метод может по-прежнему изменять содержимое объекта, он просто не может изменить объект, к которому относится ваша переменная.

См. мою статью о передаче параметров для получения дополнительной информации, а также мою статью о ссылочных типах и типах значений .

...