Вопрос

Итак, если я выполняю итерацию с использованием цикла foreach и у меня внутри есть функция, которая принимает аргумент объекта, повторяемого из списка, и, скажем, я установил для него другое значение.Почему мне не нужно использовать out или 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 Предварительно:1 SetFoo внутри:1 ::
БезRef SetFoo Сообщение:1 Без ссылки
SetFoo Предварительно:1 ::БезRef SetFoo
Внутри:1 ::Без ссылки::WithRef
Сообщение SetFoo:1 Без ссылки ::WithRef

SetFoo Предварительно:2 SetFoo внутри:2 ::
БезRef SetFoo Сообщение:2 Без ссылки
SetFoo Предварительно:2 ::БезRef SetFoo
Внутри:2 ::Без ссылки::WithRef
Сообщение SetFoo:2 Без ссылки ::WithRef

SetI Pre:0 SetI Внутри:2 SetIPost:0

SetRefI Pre:0 SetRefI Внутри:3
Сообщение SetRefI:3

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

Спасибо!

Это было полезно?

Решение

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top