2013-10-01 3 views
4

Результат следующего кода меня удивил. Я думаю, что «a» должен содержать ссылку на вновь созданный объект. Может кто-нибудь объяснить, почему результат не 2?C# объект передается по ссылке или передается по значению

class Program 
{ 
    static void Main(string[] args) 
    { 
     aclass a = new aclass(); 
     Process(a); 
     Console.WriteLine(a.number); 

     Console.ReadLine(); 
    } 

    static void Process(aclass a) 
    { 
     aclass temp = new aclass(); 
     temp.number++; 
     //Console.WriteLine(temp.number); 

     a = temp; 
     a.number++; 
     //Console.WriteLine(a.number); 
    } 

} 

class aclass 
{ 
    public int number = 0; 
} 

Редактировать: Это вопрос интервью. Я просто понял, что давно не понял эту концепцию. Аргумент a отличается от оригинала a, хотя они ссылаются на один и тот же адрес.

+2

Потому что, когда вы делаете 'а = temp' вы вызвать разрыв между аргументом, который был принят, и что вы собираетесь быть изменения с этого момента. Если вы этого не сделали, вы получите '1' в' Main'. – Jon

+0

В C# args передаются по значению не по ссылке, посмотрите ключевое слово [ref] (http://msdn.microsoft.com/en-us/library/14akc2c7.aspx). –

+1

Вы увеличиваете 'число' на' temp' дважды, но вы не работаете над 'a', определенным в' Main'. – Sam

ответ

10

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

В этом случае конкретно вы хотели бы использовать ref, как вы также передать ссылку в

Try:.

class Program 
{ 
    static void Main(string[] args) 
    { 
     aclass a = new aclass(); 
     Process(ref a); 
     Console.WriteLine(a.number); 

     Console.ReadLine(); 
    } 

    static void Process(ref aclass a) 
    { 
     aclass temp = new aclass(); 
     temp.number++; 
     //Console.WriteLine(temp.number); 

     a = temp; 
     a.number++; 
     //Console.WriteLine(a.number); 
    } 

} 

Помните, вы присваиваете целую новую ссылку с a = temp. Если вы просто хотели, чтобы обновить существующий класс, первоначально принятый в то вы могли бы сделать:

a.number = temp.number; 
a.number++; 

Это отрицают бы необходимость ref.

Вы можете прочитать на сайте MSDN:

Passing Reference Type Parameters

ref Keyword

out Keyword

+0

Это прояснило мое недоразумение в отношении аргумента и исходного объекта. Аргумент a - это другой объект, кроме оригинала a, хотя первоначально они ссылаются на одно и то же значение. – mortdale

0

Эта линия aclass a = new aclass(); создает переменную (пространство, где мы можем хранить данные) в памяти. Считают, что его адрес в памяти *(0x12DF) и value, который хранится в этом месте находится объект a

Эта линия Process(a) проходит VALUE объекта aНЕ АДРЕС функционировать Process, так что все происходит в Process() не имеет никакого отношения к делать с contents местоположения *(0x12DF), поэтому содержимое местоположения *(0x12DF) останется таким же, как было до звонка Process().

СОДЕРЖАНИЕ *(0x12DF) = а

Я надеюсь, что его полезным вместо того, чтобы создать больше путаницы !!

+0

Я думаю _Process (a) _ передает адрес содержимого. Аргумент в _Process (aclass a) _ - это новый объект, указывающий на тот же контент 0x12DF. Содержимое в 0x12DF никогда не дублировалось. Было бы более эффективно передавать адрес, чем передавать все значение. Если _aclass_ является типом значения, аргумент _a_ будет новым объектом со значением, дублируемым на другом адресе. – mortdale

0

Это в основном разница между

  • Прохождение ссылочных типов по значению // Способ (а);
  • Передача ссылочных типов по ссылкам // Процесс (ref a);

В примере процесс (a) - 'a', который является ссылочным типом, передается методу без параметра ref.В этом случае копия ссылки, которая указывает на a, передается методу.

Выделение новой части памяти с помощью нового оператора внутри метода Process делает переменную 'a' ссылкой новым объектом aclass. Таким образом, любые изменения после этого не будут влиять на исходный объект «a».

См MSDN: http://msdn.microsoft.com/en-us/library/s6938f28.aspx

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