1

I've got the following class:

public class FolderAgent
    {
        public string directoryName {get; private set; }
        public int numberofdirectories {get; private set; }
        public int numberofFiles {get; private set;}
        public DirectoryInfo [] directories {get; private set;}
        public FileInfo [] files {get; private set;}

        public FolderAgent(string directoryName, int numberofdirectories, int numberofFiles, DirectoryInfo [] listDir, FileInfo [] listFiles)
        {
            this.directoryName = directoryName;
            this.numberofdirectories = numberofdirectories;
            this.numberofFiles = numberofFiles;
            Array.Copy(listDir, directories, listDir.Length);
            Array.Copy(listFiles, files, listFiles.Length);
        }
    }

I have another class that will take folderagent as a parameter in the constructor, is this the correct way of creating a defensive copy of the Folderagent object?

public class FolderKey
    {

        public FolderAgent folder {get; private set;}
        public int returnValue {get; private set;}

        public FolderKey(FolderAgent folder, int returnValue)
        {
            this.folder = new FolderAgent(folder.directoryName, folder.numberofdirectories, folder.numberofFiles, folder.directories, folder.files);
            this.returnValue = returnValue;
        }
    }
  • You are close, if not correct... you will get a copy for each name, numberOfDir, and numberOfFiles. You will also create new arrays for both your `DirectoryInfo[]` and `FileInfo[]`. However, every single element of `FileInfo` and `DirectoryInfo` in your `FileInfo[]` and `DirectoryInfo[]` will still share the same reference to the original folder... Which should not be an issue as long as you do not mean to write anything to them. – Ian Feb 17 '16 at 15:48
  • @Ian - Could you show me how to create a defensive copy of arrays then, because I intend to delete the files and folders in directory provided. –  Feb 17 '16 at 15:50
  • @Ian - I think array.clone is the proper choice here. –  Feb 17 '16 at 15:54
  • What you have done for array is actually okay, it is correct - you have duplicated your array. What happen in one array (such as you put it to null), will not affect another array. But the element of the array in you case is `class`, these are the ones which are not copied, and making defensive copy of a `class` is really troublesome. You can check some other posts to find out a good strategy though: http://stackoverflow.com/questions/2954791/how-do-i-make-defensive-copy-of-an-object?rq=1 – Ian Feb 17 '16 at 15:55
  • If, by the time you create your defensive copy, all `FileInfo` and `DirectoryInfo` structures are "valid" (i.e., you just created those objects so the cached data in them is current), then making a copy would be trivial: just create new instances with the path in the original files. Using "unrefreshed" instances of `FileInfo` and `DirectoryInfo` is not really all that common (that's why `Refresh` exists on them) – Jcl Feb 17 '16 at 16:34
  • @Jcl - Could you change my code and show me how? –  Feb 17 '16 at 16:40

1 Answers1

0

You basically want a copy of all elements of the array. Note that FileInfo and DirectoryInfo use cached data which gets initialized the first time you access any of the file/directory properties.

So you might just aswell recreate the objects, instead of making a copy... something like (untested):

public FolderAgent(string directoryName, int numberofdirectories,
                   int numberofFiles, DirectoryInfo [] listDir, 
                   FileInfo [] listFiles)
{
    this.directoryName = directoryName;
    this.numberofdirectories = numberofdirectories;
    this.numberofFiles = numberofFiles;

    directories = new DirectoryInfo[listDir.length];
    for(var i = 0; i < listDir.length; i++)
      directories[i] = new DirectoryInfo(listDir[i].FullName);

    files = new FileInfo[listFiles.length];
    for(var i = 0; i < listFiles.length; i++)
      files[i] = new FileInfo(listFiles[i].FullName);
}
Jcl
  • 27,696
  • 5
  • 61
  • 92
  • How would [i] get incremented? –  Feb 17 '16 at 16:48
  • Ooops, my bad, I made a `for` loop, then changed to `foreach` but didn't think about that. **Updated** – Jcl Feb 17 '16 at 16:48
  • Note that I haven't tested this, but it *should* work. Then again, all properties involving file/directory attributes of `FileInfo` and `DirectoryInfo` will get cached the first time you access any of those properties, so you can't count on those properties being equal if your filesystem has changed. Then again, that's not the mission of `DirectoryInfo` or `FileInfo`, so if you need that (caching of the file/directory data), you'd be better off creating your own classes, instead of relying on those – Jcl Feb 17 '16 at 16:51
  • @Spaceman A side note too (but that depends on what you want this for), `numberofFiles` and `numberofdirectories` might be redundant to have if they are just the length of the arrays – Jcl Feb 17 '16 at 16:56
  • I'm creating a small utility for clearing a folder, and have to determine if files/sub directories exist. If it's greater than 0 then we have files/folders, but I understand what you're getting at. –  Feb 17 '16 at 16:58
  • And you need to store all the `DirectoryInfo` and `FileInfo` structures and make a defensive copy for that? – Jcl Feb 17 '16 at 17:05
  • Not really, I learned about defensive copying for immutable objects and wanted to learn how to implement it in my own projects. –  Feb 17 '16 at 17:09
  • Ok if it's for learning purposes. Be wary though, `FileInfo` and `DirectoryInfo` are far from immutable. If anything, they are one of the most mutable classes in the .NET Framework. Almost all their properties will change their state based on many different external factors (like... the filesystem) :-) – Jcl Feb 17 '16 at 17:10