C# объект передается по ссылке или по значению
Вывод следующего кода меня удивил. Я думаю, что "а" должен содержать ссылку на вновь созданный объект. Может кто-нибудь объяснить, почему результат не 2?
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, хотя они ссылаются на один и тот же адрес.
3 ответа
Вы не изменяете фактическую исходную ссылку, вы просто изменяете ссылку, содержащуюся в параметре, что не совсем то же самое, изменения не сохраняются обратно к вызывающей стороне. Вы можете изменить это поведение, используя out
или же ref
,
В этом случае конкретно вы хотели бы использовать ref
как вы также передаете ссылку в.
Пытаться:
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:
Эта линия aclass a = new aclass();
создает переменную (пространство, где мы можем хранить данные) в памяти. Учтите, что его адрес в памяти *(0x12DF)
и value
который хранится в этом месте является объектом a
Эта линия Process(a)
проходит VALUE
объекта a
НЕ АДРЕС, чтобы функционировать Process
так что-нибудь происходит в Process()
не имеет ничего общего с contents
местоположения *(0x12DF)
так что содержимое локации *(0x12DF)
останется таким же, как было до звонка Process()
,
СОДЕРЖАНИЕ *(0x12DF)
= а
Я надеюсь, что это полезно, а не создавать больше путаницы!
Это в основном разница между
- Передача ссылочных типов по значению // Process(a);
- Передача ссылочных типов по ссылкам // Process(ref a);
В этом примере Process(a) - "a", который является ссылочным типом, передается методу без параметра ref. В таком случае копия ссылки, которая указывает на a, передается методу.
Выделение новой части памяти с помощью оператора new внутри метода Process делает переменную 'a' ссылкой на новый объект класса. Таким образом, любые изменения после этого не будут влиять на исходный объект "а".
См. MSDN: http://msdn.microsoft.com/en-us/library/s6938f28.aspx