在 class 构造函数中使用 using 语句是否有意义?

Does it make sense to have using statement inside class constructor?

我的意思是在 class 的构造函数中使用下面的语句 我使用 FileSystemWatcher 实例,在 class 构造函数中使用 using 语句是否有意义像这样或者它必须在没有 using 语句的构造函数中?

public partial class MyService : ServiceBase
        {
            FileInfo file;
            StreamWriter writer;
            FileSystemWatcher watcher1;
            FileSystemWatcher watcher2;
            FileSystemWatcher watcher3;

            public MyService()
            {
                InitializeComponent();

                file = new FileInfo(@"D:\LOGS\Log.txt");
                writer = file.CreateText();
    //I mean this using
                using (watcher1 = new FileSystemWatcher(@"C:\"))
                {
                    watcher1.Created += OnChanged;
                    watcher1.Deleted += OnChanged;
                    watcher1.Renamed += OnRenamed;
                    watcher1.Changed += OnChanged;
                    watcher1.EnableRaisingEvents = true;
                }
    //I mean this using
                using (watcher3 = new FileSystemWatcher(@"C:\Users"))
                {
                    watcher3.IncludeSubdirectories = true;
                    watcher3.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite |
                                            NotifyFilters.FileName | NotifyFilters.DirectoryName;
                    watcher3.Created += OnChanged;
                    watcher3.Deleted += OnChanged;
                    watcher3.Renamed += OnRenamed;
                    watcher3.Changed += OnChanged;
                    watcher3.Filter = "*.*";
                    watcher3.EnableRaisingEvents = true;
                }
     //I mean this using
                using (watcher2 = new FileSystemWatcher(@"D:\"))
                {
                    watcher2.IncludeSubdirectories = true;
                    watcher2.Created += OnChanged;
                    watcher2.Deleted += OnChanged;
                    watcher2.Renamed += OnRenamed;
                    watcher2.Changed += OnChanged;
                    watcher2.EnableRaisingEvents = true;
                }
            }

当您的服务 运行 时,您应该保持所有这些 FileSysteWatcher 实例未被处置。但是您也应该在处理服务时处理所有资源。所以最好的解决方案是通过你的服务实现 IDisposable 并在 Dispose 方法中处理所有资源。

public partial class MyService : ServiceBase
{
    FileSystemWatcher watcher1;
    FileSystemWatcher watcher2;
    FileSystemWatcher watcher3;

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            watcher1?.Dispose();
            watcher2?.Dispose();
            watcher3?.Dispose();
        }

        base.Dispose(disposing);
    }
}

还考虑将初始化逻辑移至 OnStart 服务方法。或者至少在服务启动时启用观察者并在服务停止时禁用它们:

    protected override void OnStart(string[] args)
    {
        base.OnStart(args);

        watcher1.EnableRaisingEvents = true;
        watcher2.EnableRaisingEvents = true;
        watcher3.EnableRaisingEvents = true;
    }

    protected override void OnStop()
    {
        base.OnStop();

        watcher1.EnableRaisingEvents = false;
        watcher2.EnableRaisingEvents = false;
        watcher3.EnableRaisingEvents = false;
    }

注意:别忘了处理 writer

谢尔盖的回答已经很好了,我只是想补充一些理论。

一般来说,你应该只使用在使用中声明的变量,比如

 using(var watcher = new ...)` 

因为变量是 destroyed/disposed 在 using 括号的末尾。所以永远不要在字段或属性上使用它。 using 只是一个 shorthand 的写法,在最后做一个 Dispose,也是在出现异常的情况下。如果不想在同一个方法中创建和销毁变量,则不能使用 'using'。

根据您的方法,观察者是 disposed/destroyed,但未设置为空。所以它会导致奇怪的行为。为避免这种情况,using 中的变量不应该存在于 using 之外,它应该超出范围,这就是为什么要在 using 范围内声明变量。

一次性用品有两种模式。您可以在相同的方法中将它与 "using" 到 create/destroy 一起使用,或者将其包含在一次性 class 中。您在 class 中创建它,并在处置拥有的 class 时处置它。在拥有 class 上再次应用相同的规则,也许拥有 class 可以与 using 块一起使用。 Sergeys 的实现假定,您的外部 class 派生自已经实现 IDisposable 的 class。