﻿# V3178\. Calling method or accessing property of potentially disposed object may result in exception\.

Анализатор обнаружил вызов метода или обращение к свойству объекта, у которого ранее был вызван метод 'Dispose' или его аналог\. Подобные действия могут привести к выбрасыванию исключения\.

Рассмотрим пример: 

```cpp
public void AppendFileInformation(string path)
{
  FileStream stream = new FileStream(path,
                                     FileMode.Open,
                                     FileAccess.Read);
  ....
  stream.Close();
  ....
  if (stream.Length == stream.Position)
  {
    Console.WriteLine("End of file has been reached.");
    ....
  }
  ....
}
```

В условии проверяется, что файл был прочитан полностью\. Для проверки сравнивают текущую позицию потока и его длину\. Проблема в том, что при обращении к свойству 'Length' будет выброшено исключение типа 'ObjectDisposedException'\. Это связано с тем, что перед условием у переменной 'stream' вызывается метод 'Close'\. Для класса 'FileStream' этот метод является аналогом 'Dispose'\. Следовательно, ресурсы 'stream' будут освобождены\.

Рассмотрим корректную реализацию 'AppendFileInformation': 

```cpp
public void AppendFileInformation(string path)
{
  using (FileStream stream = new FileStream(path,
                                            FileMode.Open,
                                            FileAccess.Read))
  {
    ....
    if (stream.Length == stream.Position)
    {
      Console.WriteLine("End of file has been reached.");
    }
    ....
  }
  ....
}
```

Для корректной работы метода стоит использовать выражение 'using'\. В этом случае:

* ресурсы объекта 'stream' будут автоматически освобождены после выхода из тела 'using';
* вне тела 'using' обратиться к объекту не получится – это даёт дополнительную защиту от исключений типа 'ObjectDisposedException';
* даже если в теле 'using' возникнет исключение, ресурсы всё равно будут освобождены\. 

Ещё один вариант ошибки выглядит следующим образом: 

```cpp
public void ProcessFileStream(FileStream stream)
{
  ....
  bool flag = CheckAndCloseStream(stream);
  AppendFileInformation(stream);
  ....
}

public bool CheckAndCloseStream(FileStream potentiallyInvalidStream)
{
  ....
  potentiallyInvalidStream.Close();
  ....
}

public void AppendFileInformation(FileStream streamForInformation)
{
  ....
  if (streamForInformation.Length == streamForInformation.Position)
  {
    Console.WriteLine("End of file has been reached.");
  }
  ....
}
```

После вызова 'CheckAndCloseStream' в методе 'ProcessFileStream' ресурсы объекта, на который ссылается переменная 'stream', будут освобождены\. Далее эта переменная передаётся в метод 'AppendFileInformation'\. Внутри него производится обращение к свойству 'Length', из\-за чего будет выброшено исключение типа 'ObjectDisposedException'\. 

Корректная реализация 'ProcessFileStream' будет выглядеть следующим образом:

```cpp
public void ProcessFileStream(FileStream stream)
{
  ....
  AppendFileInformation(stream);
  bool flag = CheckAndCloseStream(stream);
  ....
}
```

Был изменён порядок вызовов методов 'CheckAndCloseStream' и 'AppendFileInformation'\. Вследствие этого ресурсы будут освобождаться уже после выполнения действий над потоком\. Следовательно, исключение выброшено не будет\.