Наткнулся на такой необычный код на 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
Ваш код с 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; происходит не изменение переменной, а изменение объекта, на который она указывает.
Сборка персонального компьютера от Artline: умный выбор для современных пользователей