#c_sharp #net #dispose
Наткнулся на такой необычный код на METANIT. Объявлена структура: public struct S : IDisposable { private bool dispose; public void Dispose() { dispose = true; } public bool GetDispose() { return dispose; } } И есть такой код, который использует ее: var s = new S(); using (s) { Console.WriteLine(s.GetDispose()); } Console.WriteLine(s.GetDispose()); Код выводит false, false, хотя казалось, что должно выводиться false, true. Самое интересное то, что если структуру S сделать классом, то будет выводиться ожидаемое значение :) Объясните, что происходит за кулисами с переменной s? Почему для структуры будет false, false, а для класса - false, true
Ответы
Ответ 1
Ваш код с using разворачивается следующим образом: var s = new S(); var using_s = s; try { Console.WriteLine(s.GetDispose()); } finally { using_s.Dispose(); } Console.WriteLine(s.GetDispose()); using вызыват Dispose не на вашей переменной s а на своей собственной переменной. И соответственно поле dispose обновляется не у переменной s. Для примера можно рассмотреть следующий код: using System; public static class Program { public static void Main() { var s = new S(); using (s) { s.Mark = 42; Console.WriteLine(s.GetDispose()); } Console.WriteLine(s.GetDispose()); var c1 = new C(); using (c1) { c1.Mark = 42; Console.WriteLine(c1.GetDispose()); } Console.WriteLine(c1.GetDispose()); var c2 = new C(); using (c2) { c2 = new C { Mark = 42 }; Console.WriteLine(c2.GetDispose()); } Console.WriteLine(c2.GetDispose()); } } public struct S : IDisposable { public int Mark; private bool dispose; public void Dispose() { Console.WriteLine(Mark); dispose = true; } public bool GetDispose() { return dispose; } } public class C : IDisposable { public int Mark; private bool dispose; public void Dispose() { Console.WriteLine(Mark); dispose = true; } public bool GetDispose() { return dispose; } } В случаях s.Mark = 42; и c2 = new C { Mark = 42 }; назначение переменной внутри блока using не влияет на значение поля Mark, выводимое методом Dispose, так как using вызывает Dispose на своей собственной переменной. И компилятор даже выводит соответствующие предупреждение. В случае с c1.Mark = 42; происходит не изменение переменной, а изменение объекта, на который она указывает.
Комментариев нет:
Отправить комментарий