Каково использование “касательно” для переменных ссылочного типа в C#?

Я понимаю это, если я передаю тип значения (int, struct, и т.д.) в качестве параметра (без ref ключевое слово), копия той переменной передается методу, но если я использую ref ключевое слово ссылка на ту переменную передается, не новая.

Но со ссылочными типами, как классы, даже без ref ключевое слово, ссылка передается методу, не копии. Таким образом, каково использование ref ключевое слово со ссылочными типами?


Возьмите, например:

var x = new Foo();

Каково различие между следующим?

void Bar(Foo y) {
    y.Name = "2";
}

и

void Bar(ref Foo y) {
    y.Name = "2";
}
167
задан Peter Mortensen 19 August 2012 в 22:07
поделиться

6 ответов

Вы можете изменить то, на что указывает foo , используя y :

Foo foo = new Foo("1");

void Bar(ref Foo y)
{
    y = new Foo("2");
}

Bar(ref foo);
// foo.Name == "2"
149
ответ дан 23 November 2019 в 21:00
поделиться

Есть случаи, когда вы хотите изменить фактическую ссылку , а не объект, на который указывает:

void Swap<T>(ref T x, ref T y) {
    T t = x;
    x = y;
    y = t;
}

var test = new[] { "0", "1" };
Swap(ref test[0], ref test[1]);
29
ответ дан 23 November 2019 в 21:00
поделиться

Джон Скит написал отличную статью о передаче параметров в C #. Он четко описывает точное поведение и использование передачи параметров по значению, по ссылке ( ref ) и по выходу ( out ).

Вот важная цитата с той страницы в отношение к параметрам ref : значения переменных, используемых в вызов функции-члена - они используют сами переменные. Скорее, чем создание нового хранилища для переменная в члене функции декларация, то же место хранения используется, поэтому значение переменной в члене функции и значении ссылочного параметра всегда будет быть таким же. Необходимые справочные параметры модификатор ref как часть декларация и призыв - это значит всегда ясно, когда ты передача чего-либо по ссылке.

18
ответ дан 23 November 2019 в 21:00
поделиться

Когда вы передаете ссылку введите ключевое слово ref, вы передаете ссылку по ссылке, и вызываемый вами метод может присвоить параметру новое значение. Это изменение распространится на вызывающую область. Без ref ссылка передается по значению, а этого не происходит.

В C # также есть ключевое слово out, которое очень похоже на ref, за исключением того, что с ref, аргументы должны быть инициализированы перед вызовом метода. , а с "out" вы должны присвоить значение в методе получения.

9
ответ дан 23 November 2019 в 21:00
поделиться

Это позволяет вам изменять переданная ссылка. например

void Bar()
{
    var y = new Foo();
    Baz(ref y);
}

void Baz(ref Foo y)
{
    y.Name = "2";

    // Overwrite the reference
    y = new Foo();
}

Вы также можете использовать out , если вас не волнует переданная ссылка:

void Bar()
{
    var y = new Foo();
    Baz(out y);
}

void Baz(out Foo y)
{
    // Return a new reference
    y = new Foo();
}
5
ответ дан 23 November 2019 в 21:00
поделиться

Еще одна связка кода

class O
{
    public int prop = 0;
}

class Program
{
    static void Main(string[] args)
    {
        O o1 = new O();
        o1.prop = 1;

        O o2 = new O();
        o2.prop = 2;

        o1modifier(o1);
        o2modifier(ref o2);

        Console.WriteLine("1 : " + o1.prop.ToString());
        Console.WriteLine("2 : " + o2.prop.ToString());
        Console.ReadLine();
    }

    static void o1modifier(O o)
    {
        o = new O();
        o.prop = 3;
    }

    static void o2modifier(ref O o)
    {
        o = new O();
        o.prop = 4;
    }
}
4
ответ дан 23 November 2019 в 21:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: