2013-09-20 2 views
2

Рассмотрим следующий фрагмент кода (написанный в форме для Windows Application):Передача этого по ссылке (ссылка это)

public partial class Form1 
{ 
    .... 
    public void Caller() 
    { 
     Form1 myRef = this; 
     Change(ref this) //--> won't compile because *this* is read-only 
     Change(ref myRef); //--> compiles but doesn't work. 
    } 
    .... 

    public void Change(ref Form1 theRef) 
    { 
     theRef = new Form1(); 
     theRef.Text = "I am a new form"; 
    } 
} 

Passing this по ссылке не allowd. Это нормально и разумно. Но почему передача this косвенно, как показано выше, не работает? Поскольку я знаю, передается ли параметр по ссылке, любое присваивание в вызываемом методе отражается методу вызывающего. Почему здесь не работает?

Update, чтобы сделать этот вопрос ясный

1- Я не изо всех сил, чтобы достигнуть чего-нибудь особенного. Я просто пытаюсь проверить ref.

2- Причина, почему я неправильно понял ref, что я совершенно забыл Form1 myRef = this фактически копии адрес основной Form1 объект myRef; поэтому переменная myRef не имеет ничего общего с this, за исключением того, что оба они указывают на один и тот же объект.

+1

Что именно вы пытаетесь достичь здесь? – Rik

+1

Конечно, второй вызов работает, он просто изменяет переменную 'myRef' ** ** в' Caller'. Вы не можете изменить 'this' для ссылочного типа, периода. –

+0

Изменить это косвенно не возможно, но значение myRef будет изменено – Blau

ответ

7

Он работает так, как должен. Проблема в том, что это не то же самое, что вы ожидаете.

Form1 myRef = this; 
var b1 = object.ReferenceEquals(myRef, this); // true 
Change(ref myRef); 
var b2 = object.ReferenceEquals(myRef, this); // false 

Таким образом, значение myRef изменяется. Не следует распространять это изменение на this; после выполнения задания myRef и this являются полностью отдельными переменными. У C# нет «переменных ref», так что это не могло быть иначе (даже если бы это было, переназначение таким образом никогда не было разрешено).

3

Использование myRef действительно работает, после вызова метода это фактически будет ссылкой на новый экземпляр формы. Он также изменит свойство Text, но вы ничего не увидите, потому что вы не показываете свой новый экземпляр формы. Это не того же экземпляра, что и ваша первоначальная форма (this), так что форма не будет изменена каким-либо образом.

Если вы хотите изменить свойство формы вы можете сделать это следующим образом:

public void Change(Form1 theRef) 
{ 
    theRef.Text = "I am a new form"; 
} 

который можно назвать так:

Change(this); 

Но вы не можете создать «новую форму «заменить существующий такой. Возможно, вам стоит подумать о какой-то функции Reset(), которая очищает форму по мере необходимости.

Если вам действительно нужно заменить текущую форму, вам понадобится какой-то «родительский», который может управлять исходной формой.

1

Потому что вы не можете присвоить значение this.

+1

... * в справочной форме *. Хотя изменение его в типе значений допускается, оно иногда не делает того, что, по вашему мнению, оно будет делать, поэтому оно также должно было быть отклонено. –

+0

@ LasseV.Karlsen это можно сделать в виде структуры? – Blau

+0

Не передавайте 'this' по ссылке *, но вы можете присвоить значение' this', конечно. –

1

На самом деле это работает. Я предполагаю, что вы ожидаете, что ваша текущая форма изменится, однако это не будет работать так. Что делает ваш код, это изменение содержимого ссылки, которую вы передаете. Он не уничтожает/не заменяет вашу текущую форму.

Что вам нужно сделать, это что-то вроде

  • Создать (новый) форму и открыть его (.Show или .ShowDialog)
  • Уничтожить текущую форму (.close)
0

В ссылочных типах this доступен только для чтения, нет никакого способа обойти это.

Ваш второй вызов действительно работает, но он изменяет переменную myRef для ссылки на новую форму. this все еще относится к оригинальной форме, так как вы не можете изменить это в любом случае.

Этот ответ только более полный ответ на комментарий выше, чтобы уточнить, что this не только для чтения всюду в C# /. NET.

В типе значения вы можете присвоить новое значение this, но вы по-прежнему не можете передать this по ссылке, поэтому ваш код все равно не будет работать.

Однако здесь приведен пример присвоения нового значения this, который «работает» в типе значения.

void Main() 
{ 
    Test t = new Test(17); 
    t.Dump(); 
    t.StrangeMutation(); 
    t.Dump(); 
} 

public struct Test 
{ 
    public readonly int Value; 

    public Test(int value) 
    { 
     Value = value; 
    } 

    public void StrangeMutation() 
    { 
     this = new Test(42); 
    } 
} 

Обратите внимание, что Value поле только для чтения, так что кажется, нет никакого способа, что поле должно изменить свое значение, однако выход из вышеуказанной программы является то, что первое поле имеет значение 17, в следующий раз мы проверим его значение 42.

Это, однако, только работает в типах значений. Он не работает со ссылочными типами, и вы также не можете проходить по ссылке.

Смежные вопросы