Search code examples
c#constructordisposeusing-statement

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


I mean using the statement below, inside the constructor of my class I use FileSystemWatcher instance, does it make sense to have using statement inside class constructor like this or it must be inside constructor without using statement?

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;
                }
            }

Solution

  • You should keep all this FileSysteWatcher instances non-disposed while your service is running. But you also should dispose all resources when service is disposed. So the best solution is to implement IDisposable by your service and dispose all resources in the Dispose method.

    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);
        }
    }
    

    Consider also to move initialization logic to OnStart method of service. Or at least enable watchers on service start and disable them on service stop:

        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;
        }
    

    Note: don't forget to dispose writer as well.