1

I lifted some code to compare two directories, and it all works fine, but I wanted to improve it for my purposes so I can recycle the code for slightly different requirements. The original code listed all directories, but I wanted to add in a switch so I could decide whether to list all directories or the top level only. Here is a snippet from my code;

public void DoCompare(string pathA, string pathB, bool allDirs)
{
    DirectoryInfo dir1 = new DirectoryInfo(pathA);
    DirectoryInfo dir2 = new DirectoryInfo(pathB);

    if (allDirs)
    {
        IEnumerable<FileInfo> list1 = dir1.GetFiles("*.*", SearchOption.AllDirectories);
        IEnumerable<FileInfo> list2 = dir2.GetFiles("*.*", SearchOption.AllDirectories);
    }
    else
    {
        IEnumerable<FileInfo> list1 = dir1.GetFiles("*.*", SearchOption.TopDirectoryOnly);
        IEnumerable<FileInfo> list2 = dir2.GetFiles("*.*", SearchOption.TopDirectoryOnly);
    }

    //A custom file comparer defined later
    FileCompare myFileCompare = new FileCompare();

    bool areIdentical = list1.SequenceEqual(list2, myFileCompare);

Now without the if (allDirs) this works fine. When I put that in, list1 and list 2 are not visible in the last line of code. The actual error is "The name list1 does not exist in the current context". I tried declaring them outside the if, but that relied on them returning results, which isn't possible without the decision. So how do I make these visible outside the if statement?

Gilad Green
  • 36,708
  • 7
  • 61
  • 95
SkinnyPete63
  • 597
  • 1
  • 5
  • 20
  • Possible duplicate of [Variable scope confusion in C#](https://stackoverflow.com/questions/1196941/variable-scope-confusion-in-c-sharp) – Paul Karam Jul 21 '17 at 08:59

4 Answers4

4

It's not accessible because it's declared in an inner scope that is not visible in the outer scope. But you just want to change the SeachOption according to the bool, so why not simply:

SearchOption opt = allDirs ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
IEnumerable<FileInfo> list1 = dir1.GetFiles("*.*", opt);
IEnumerable<FileInfo> list2 = dir2.GetFiles("*.*", opt);
bool areIdentical = list1.SequenceEqual(list2, new FileCompare());

If you couldn't do that you have to declare it outside:

IEnumerable<FileInfo> list1;
IEnumerable<FileInfo> list2;
if(allDirs)
{
    list1 = ...
    list2 = ...
}
else
{
   list1 = ...
   list2 = ...
}
// now you can access them here because they are declared in the same scope
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
2

They are not accessible as they are defined in the scopes of the if/else. For more about accessibility of variables in scopes

You can define them outside as in Mark's answer but instead change the if else to only take care of which SearchOption. That way you have no code repitition:

var option = allDirs ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;

IEnumerable<FileInfo> list1 = (new DirectoryInfo(pathA)).GetFiles("*.*", option);
IEnumerable<FileInfo> list2 = (new DirectoryInfo(pathB)).GetFiles("*.*", option);

bool areIdentical = list1.SequenceEqual(list2, new FileCompare());
Gilad Green
  • 36,708
  • 7
  • 61
  • 95
1

Its simple, declare them outside if statement and assign inside:

public void DoCompare(string pathA, string pathB, bool allDirs)
{
    DirectoryInfo dir1 = new DirectoryInfo(pathA);
    DirectoryInfo dir2 = new DirectoryInfo(pathB);

    IEnumerable<FileInfo> list1; // declare list1 here
    IEnumerable<FileInfo> list2; // declare list2 here

    if (allDirs)
    {
        list1 = dir1.GetFiles("*.*", SearchOption.AllDirectories);
        list2 = dir2.GetFiles("*.*", SearchOption.AllDirectories);
    }
    else
    {
        list1 = dir1.GetFiles("*.*", SearchOption.TopDirectoryOnly);
        list2 = dir2.GetFiles("*.*", SearchOption.TopDirectoryOnly);
    }

    //A custom file comparer defined later
    FileCompare myFileCompare = new FileCompare();

    bool areIdentical = list1.SequenceEqual(list2, myFileCompare);
}

It's not accessible because it's declared in an inner scope that is not visible in the outer scope.

You can also simplify that method using conditional operator ?.

IEnumerable<FileInfo> list1 = dir1.GetFiles("*.*", allDirs ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
Markiian Benovskyi
  • 2,137
  • 22
  • 29
1

You could also use the ternary operator und change this

if (allDirs)
{
    IEnumerable<FileInfo> list1 = dir1.GetFiles("*.*", SearchOption.AllDirectories);
    IEnumerable<FileInfo> list2 = dir2.GetFiles("*.*", SearchOption.AllDirectories);
}
else
{
    IEnumerable<FileInfo> list1 = dir1.GetFiles("*.*", SearchOption.TopDirectoryOnly);
    IEnumerable<FileInfo> list2 = dir2.GetFiles("*.*", SearchOption.TopDirectoryOnly);
}

to this:

IEnumerable<FileInfo> list1 = allDirs?dir1.GetFiles("*.*", SearchOption.AllDirectories):dir1.GetFiles("*.*", SearchOption.TopDirectoryOnly);
IEnumerable<FileInfo> list2 = allDirs?dir2.GetFiles("*.*", SearchOption.AllDirectories):dir2.GetFiles("*.*", SearchOption.TopDirectoryOnly);
Rob
  • 11,492
  • 14
  • 59
  • 94