Действительно ли возможно вызвать использование “использования” для доступных классов?

Я должен вынудить использование "использования" расположить новый экземпляр класса.

public class MyClass : IDisposable
{
   ...
}

using(MyClass obj = new MyClass()) // Force to use "using"
{
}
33
задан Zanoni 20 April 2010 в 13:38
поделиться

8 ответов

Тот факт, что вам нужно , чтобы гарантировать, что объект удален, указывает на конструктивный недостаток. Это нормально, если удаление является вежливым или эффективным делом, но это не должно быть семантически необходимым .

Невозможно принудительно удалить объект с помощью оператора using . Однако вы можете поддерживать в объекте флаг, который указывает, был ли объект удален, а затем написать финализатор, который проверяет этот флаг. Если финализатор обнаруживает, что объект не был удален, то вы можете попросить финализатор, скажем, завершить процесс через failfast. То есть настолько строго наказать пользователя, который не позаботился об удалении объекта, что он вынужден либо исправить свою ошибку, либо прекратить использование вашего объекта.

Это не кажется мне хорошим, хорошим или вежливым, но вы единственный, кто знает, каковы ужасные, ужасные последствия неспособности избавиться от предмета. Вам решать, лучше ли применять наказание к людям, которые не соблюдают ваши безумные правила, чем жить с последствиями их несоблюдения.

45
ответ дан 27 November 2019 в 17:42
поделиться

Это некрасиво, но вы можете сделать что-то вроде этого:

    public sealed class DisposableClass : IDisposable
    {
        private DisposableClass()
        {

        }

        public void Dispose()
        {
            //Dispose...
        }

        public static void DoSomething(Action<DisposableClass> doSomething)
        {
            using (var disposable = new DisposableClass())
            {
                doSomething(disposable);
            }
        }
    }
21
ответ дан 27 November 2019 в 17:42
поделиться

Оператор using - это сокращение, которое компилятор преобразует из:

(using DisposableObject d = new DisposableObject()){}

в:

DisposableObject d = new DisposableObject()
try
{

}
finally
{
    if(d != null) d.Dispose();
}

, поэтому вы более или менее спрашиваете, можно ли принудительно написать блок try / finally, который вызывает Dispose для объекта.

5
ответ дан 27 November 2019 в 17:42
поделиться

Нет, вы не можете этого сделать. Вы даже не можете заставить их вызвать утилизацию. Лучшее, что вы можете сделать, это добавить финализатор. Просто имейте в виду, что финализатор будет вызван, когда объект будет удален, и это зависит от времени выполнения.

1
ответ дан 27 November 2019 в 17:42
поделиться

Нет, это невозможно. Теперь вы можете вызвать метод dispose в финализаторе класса (а затем вы можете запретить его использование, если они действительно вызывают метод dispose). Таким образом, он сработает, если это не сделано явно в коде.

Эта ссылка покажет вам, как реализовать шаблон финализатора / удаления:

http://www.devx.com/dotnet/Article/33167

1
ответ дан 27 November 2019 в 17:42
поделиться

Если вы хотите принудительно использовать using в этом классе, ваш код для поддержки этого класса вы можете кодировать в другом классе и скрыть MyClass для нормального использования.

0
ответ дан 27 November 2019 в 17:42
поделиться

Вам следует изучить RAII , который представляет собой метод, обеспечивающий правильное использование полученных ресурсов.

Я имею в виду, что если вы не можете принудительно вызвать метод Dispose (через с использованием или напрямую), вы можете поместить его содержимое в другой метод, который будет вызывается, например деструктор.

Это общий шаблон для реализации IDisposable , как показано ниже:

// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
    Dispose(true);
    // This object will be cleaned up by the Dispose method.
    // Therefore, you should call GC.SupressFinalize to
    // take this object off the finalization queue 
    // and prevent finalization code for this object
    // from executing a second time.
    GC.SuppressFinalize(this);
}

// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the 
// runtime from inside the finalizer and you should not reference 
// other objects. Only unmanaged resources can be disposed.
private void Dispose(bool disposing)
{
    // Check to see if Dispose has already been called.
    if(!this.disposed)
    {
        // If disposing equals true, dispose all managed 
        // and unmanaged resources.
        if(disposing)
        {
            // Dispose managed resources.
            component.Dispose();
        }

        // Call the appropriate methods to clean up 
        // unmanaged resources here.
        // If disposing is false, 
        // only the following code is executed.

        // TODO: write code
    }
    disposed = true;         
}

// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method 
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~ClassName()
{
    // Do not re-create Dispose clean-up code here.
    // Calling Dispose(false) is optimal in terms of
    // readability and maintainability.
    Dispose(false);
}

Источник: http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize. aspx

0
ответ дан 27 November 2019 в 17:42
поделиться

Интересно, может ли FXCop обеспечить соблюдение этого правила?

4
ответ дан 27 November 2019 в 17:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: