C # Область видимости переменных и объектов при параметризации в методы
Вопрос
Я широко использую наследование, полиморфизм и инкапсуляцию, но я только что понял, что не знаю следующего поведения области видимости объекта и переменной. Разница лучше всего показана с кодом:
public class Obj
{
public string sss {get; set;}
public Obj()
{
sss = "0";
}
}
public partial class testScope : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Obj a = new Obj();
String sss = "0";
Context.Response.Write(sss); // 0
FlipString(sss);
FlipString(a.sss);
Context.Response.Write(sss + a.sss); // 0 0
FlipObject(a);
Context.Response.Write(a.sss); // 1
Context.Response.End();
}
public void FlipString(string str)
{ str = "1"; }
public void FlipObject(Obj str)
{ str.sss = "1"; }
}
Поэтому я подумал, что когда переменная передается в метод, изменения ограничиваются областью применения метода. Но кажется, что если объект передается в метод, который изменяет свои свойства, выходит за пределы метода. Р>
Я мог бы принять это, если бы правило было таким, что такое поведение существует для объекта, а не для переменных, но в .net все является объектом, строкой (как в примере - System.String). Так что из правила, как можно я предсказываю область действия параметра, который передаю в метод?
Решение
Вы никогда не передаете объект в качестве аргумента - вы всегда передаете только ссылку или значение типа значения. Если вы не используете ключевое слово ref
, аргументы передаются по значению - т.е. начальное значение параметра является оценочным значением аргумента, а изменения в значении параметра не видны вызывающей стороне. . р>
Однако очень важно понимать, что значением параметра (для ссылочного типа) является просто ссылка . Если вы измените содержимое объекта, на который ссылается ссылка, то это изменение будет видно вызывающей стороне.
Это тема, которая заслуживает более чем нескольких параграфов. Я предлагаю вам прочитать мою статью о параметрах переходя в .NET для получения дополнительной информации.
Другие советы
Я думаю, что я только что понял, что гуглить, некоторые вещи в .net имеют " значение " типы и другие являются «справочными» типы, поэтому для типов значений значение дублируется при маршалинге в метод, но ссылочные типы имеют аналогичный указатель или ссылку, переданную в метод, который, очевидно, имеет ту же область видимости, что и родительский. Итак, мой вопрос: как определить, является ли что-то типом значения или нет, я вижу, что все структуры, такие как целые, являются типами значений, но строки выглядят как структуры, даже если они являются объектами System.String?
Класс (в вашем случае Obj) - это ссылочный тип , поэтому, когда вы вызываете функцию, вы действительно передаете ссылку (вы можете думать об этом как о типобезопасном указателе) к этому объекту. Если вы хотите предотвратить изменения в изменчивых объектах (то есть классах / ссылочных типах), то вам необходимо клонировать этот объект, прежде чем передавать его в подходящую функцию (или просто подумайте о том, чтобы сделать его структурой, чтобы она копировалась по значению). р>