Распознавать одноразовые объекты в Visual Studio?

Предполагается, что объекты IDisposable должны быть размещены в операторе using или путем вызова метода Dispose(). Я нахожу, что не интуитивно понятно, является ли объект доступным в Visual Studio.

Мой вопрос: есть ли способ распознать объекты IDisposable в VS?

Ответы

Ответ 1

Если вы хотите выделить одноразовые объекты по-разному в VS, посмотрите этот пост. Я лично предпочитаю Resharper ответить, поскольку я всегда использую R #.

Если вы просто хотите выяснить, является ли ваш объект экземпляром какого-либо интерфейса, вы можете щелкнуть правой кнопкой мыши имя переменной и Navigate -> Object Browser или Go to Declaration, а затем щелкнуть правой кнопкой мыши по имени класса Go to Definition/Peek Definition.

введите описание изображения здесь

Вам может понравиться Peek Definition, так как он показывает все, что вам нужно:

введите описание изображения здесь

Вы всегда можете проверить, что имеет объект метода, если он имеет метод Dispose(), а 99.9% - одноразовый объект. Я дам это 0,01% для тех, кто дает методы плохим именам:).

Ответ 2

Вы можете использовать Object Browser для просмотра иерархии наследования классов с реализованными интерфейсами

введите описание изображения здесь

Ответ 3

Для полноты, если вы не спросите, как проверить это в своем коде, но вы просто хотите знать, где вы можете посмотреть, реализует ли тип интерфейса, например IDisposable, вы всегда можете посмотреть MSDN.

Например FileStream

  • это уже упоминалось в разделе замечаний:

Этот тип реализует интерфейс IDisposable. Когда вы закончите используя этот тип, вы должны распоряжаться им либо напрямую, либо косвенно. Чтобы удалить этот тип напрямую, вызовите его метод Dispose в блоке try/catch. Чтобы избавиться от него косвенно, используйте язык построить, например, используя (в С#) или Использовать (в Visual Basic). Для большего информацию см. в разделе "Использование объекта, который реализует IDisposable" раздела в теме интерфейса IDisposable.

  • или найдите метод Dispose. Там вы можете увидеть, реализует ли этот класс или какой-либо родительский класс IDispable. В этом случае он наследуется от Stream, который реализует этот интерфейс, который упоминается в синтаксисе класса и в разделе замечаний.

    public abstract class Stream : MarshalByRefObject, IDisposable
    

Если вы хотите узнать, как найти реализации интерфейса в Visual Studio, вот уже вопрос, на который отвечает:

Как вы находите все реализации интерфейса?

Ответ 4

Способ увидеть, какие интерфейсы реализует класс, а также все открытые поля, свойства, методы и т.д. - это перейти к этому классу в коде. Например:

Image image = Image.FromFile(path);

Убедитесь, что вы нажимаете на класс, а не на экземпляр, и нажимаете F12. Это приведет вас к файлу метаданных для этого класса. Например: в файле Image.cs указано следующее объявление класса:

public abstract class Image : MarshalByRefObject, ISerializable, ICloneable, IDisposable

Затем вы можете использовать F12 для перехода к другим классам. Обратите внимание, что эти классы обычно отображаются в цвете Light Blue в Visual Studio:

Снимок экрана с голубыми цветами.

Вы также можете попасть в этот файл метаданных, щелкнув правой кнопкой мыши на классе и выбрав "Перейти к определению" в раскрывающемся списке.


Хотя и не идеально, вы также можете перейти к экземпляру класса и поместить в него .. Это должно вызвать intellisense, и вы сможете увидеть Dispsose() в списке, если элемент реализует интерфейс.

Вы также можете просто написать myInstance.Dispose(); или using (myInstance = new MyClass()) {}, и если он компилирует класс, он реализует интерфейс, иначе он этого не делает.

Ответ 5

Я удивлен, что никто еще не упомянул об этом. Если ваша версия версии Visual Studio поддерживает ее, я бы предложил включить Анализ кода для сборки.

После этого выберите все необходимые вам правила, если они гарантируют, что, по крайней мере, CA2000 (удалите объекты перед потерей scope), CA2213 (одноразовые поля должны быть удалены) и CA2202 (не уничтожают объекты несколько раз). Таким образом, компилятор должен кричать на вас, если вы не имеете дело с одноразовыми объектами правильно.

(Хотя обратите внимание, что получение компилятором не означает, что некорректное использование одноразовых объектов может превратиться в более сложную задачу, так как многие вопросы StackOverflow могут подтвердить)

Ответ 6

В качестве (глупой?) альтернативы обстрелу для Resharper и его ilk, Visual Studio имеет концепцию внешних инструментов (в меню "Инструменты" ), которые вы могли бы использовать (ab), чтобы сделать что-то вроде:

  • Название: Is Disposa&ble
  • Команда: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
  • Аргументы: -Command "&{$i=[Type]::GetType('System.IDisposable');[AppDomain]::CurrentDomain.GetAssemblies()|%{ $_.GetTypes()}|?{$_.FullName.EndsWith('.$(CurText)')}|%{New-Object PSObject -Property @{'Type'=$_;'IDisposable'=$i.IsAssignableFrom($_)}}|ft}"
  • Использовать окно вывода:.

Это будет читать любую строку, которую вы выбрали в редакторе, ищите типы .NET с этой строкой в ​​качестве имени и покажите True/False о том, была ли реализована эта строка IDisposable.

Команда Powershell в инструменте - это самый быстрый подход, который я мог бы сделать, чтобы продемонстрировать эту возможность, но она далека от совершенства - она ​​только находит типы в сборках, которые Powershell загружает по умолчанию. Если вы хотите расширить эту идею, вы можете создать приложение .NET из командной строки, которое загрузило ваш проект и проверило все сборки, которые ваш проект загрузил.

Если вы выделили слово Stream в своем коде, например, и запустили внешний инструмент (ALT + T, ALT + B в примере), он вернет:

Type             IDisposable
----             -----------
System.IO.Stream        True

Чтобы разбить команду Powershell:

&{ $i=[Type]::GetType('System.IDisposable');        # Get the IDisposable interface
   [AppDomain]::CurrentDomain.GetAssemblies() `     # Get all loaded assemblies
    | %{ $_.GetTypes() } `                          # For each assembly, get all types
    | ?{ $_.FullName.EndsWith('.$(CurText)') } `    # Filter types that are named $(CurText) - $(CurText) is a macro within VS External Tools
    | %{ New-Object PSObject -Property @{           # For each type, return an object containing...
         'Type' = $_;                               # ...the type name...
         'IDisposable' = $i.IsAssignableFrom($_)    # ...and whether the IDisposable interface is implemented
       } } `
    | ft }                                          # Format all returned objects as a table

Ответ 7

В качестве дополнения к Andrei отличный ответ, если вы используете С# 7, вы можете использовать этот новый синтаксис:

if(obj is IDisposable disposableObject)
{
    disposableObject.Dispose();
}

Ответ 8

either using or in Dispose() method Используйте конструкцию using, когда сможете. Вот почему. Используя этот пример MSDN, вот два эквивалентных блока кода. Этот с using:

using (Font font1 = new Font("Arial", 10.0f)) 
{
    byte charset = font1.GdiCharSet;
}

Этот без using:

{
    Font font1 = new Font("Arial", 10.0f);
    try
    {
        byte charset = font1.GdiCharSet;
    }
    finally
    {
        if (font1 != null)
            ((IDisposable)font1).Dispose();
    }
}

Каждая часть второго блока существует по какой-то причине: фигурные скобки, try-finally, нулевая проверка и листинг в IDisposable. Никто не должен помнить об этом. Вот почему существует конструкция using.

Ответ 9

Что-то чистое, что можно сделать на С# 7

class Foo : IDisposable {
    string _bar = "init";
    void Fooy() { _bar = "fooy"; }

    public void Dispose() {
        _bar = null;       
    }

    static void Main()
    {
        var v = new Foo();
        Console.WriteLine(v._bar);
        if(v is IDisposable id) using(id)
            v.Fooy();
        else
            v.Fooy();

        Console.WriteLine(v._bar ?? "null");;

    }
}

Fooy может быть некоторой виртуальной или абстрактной функцией. Некоторые базовые классы могут реализовать IDisposable, а другие нет. Попробуйте выполнить приведенный выше код. Консоль будет печатать другой текст в зависимости от того, был ли реализован IDisposable