6

I found this other stack overflow question about files and directories, and the answer included this statement:

bool isDir = (File.GetAttributes(path) & FileAttributes.Directory)
             == FileAttributes.Directory;

His question was about .net, and I was coding in C# .net in Visual Studio. Is the ability to have both an assignment operator and an equals operator in the same statement work for all .net languages or is it specific to certain ones? Also, can I get an explanation for how the above code works? Assuming that path refers to a directory, I'd expect isDir to be true, but can anyone explain why?

Community
  • 1
  • 1
Bradley Oesch
  • 763
  • 10
  • 22
  • 2
    Surely you've written code like `boolean numberEqualsFive = num == 5`, no? – Kirk Woll May 18 '12 at 20:37
  • 1
    Some more context for [precedence and order of evaluation](http://msdn.microsoft.com/en-us/library/2bxt6kc4.aspx) and [here specifically for c#](http://msdn.microsoft.com/en-us/library/aa691323(v=vs.71).aspx) – J. Holmes May 18 '12 at 20:37
  • This code checks wether the result of `File.GetAttributes` contains the binary flag bit `FileAttributes.Directory`. – user703016 May 18 '12 at 20:38
  • 2
    @KirkWoll: I doubt it. Most beginners will write `if(num == 5) someBool = true; else someBool = false;` – Ed S. May 18 '12 at 20:39
  • 3
    @vittore: Many beginners (and even some "experienced" devs...) really don't understand boolean expressions and the boolean type. I don't get it, but it is a fact. – Ed S. May 18 '12 at 20:43
  • 1
    This sort of thing is not as obvious as it seems. To a beginner, who's still trying to internalize and rationalize what code means, 'tricks' like this can be very confusing, because the beginner has an invalid mental model of what's going on. – sorpigal May 18 '12 at 20:44
  • 5
    @vittore Because everybody here at one point sucked at coding. That's why it's getting answered. To help the person out. We don't have to be smug dicks about it. – kmarks2 May 18 '12 at 20:45
  • 2
    @Kirk Of course not. I would always write that: `boolean numberEqualsFive = (num == 5);` A few extra parentheses never hurt anyone, especially when they help to ensure that code is readable and unambiguous to future maintainers! – Cody Gray - on strike May 19 '12 at 01:06
  • @Sorpigal: Was I being a "smug dick"? That wasn't my intention, I was just saying what I have seen time and time again over the years on various forums. It's not a bad thing, everyone starts somewhere. – Ed S. May 19 '12 at 19:03

6 Answers6

13

The equality test performed by the == operator takes precedence over the assignment performed by the = operator. Therefore, the isDir variable will be set equal to true if the two sides of the == operator are equal, otherwise it will be set to false. In other words, it's the equivalent of saying:

if ((File.GetAttributes(path) & FileAttributes.Directory) == FileAttributes.Directory)
    isDir = true;
else
    isDir = false;

This is possible in VB.NET. I cannot answer for other languages. In VB.NET, the equivalent would be:

Dim isDir As Boolean = ((File.GetAttributes(path) And FileAttributes.Directory) = FileAttributes.Directory)

Since VB uses the same character (=) for both it's assignment and equality-test operators, it determines which operation you are performing based on context. The VB compiler is smart enough to know that the first = operator is an assignment and the second one is an equality test. However, this is obviously confusing, so it is often discouraged, for readability sake. It's particularly confusing to people with backgrounds in other languages. For instance, in C#, you could do the following to set two variables to the same value:

int y;
int x = y = 5;  // Both x and y will be set to 5

The reason that happens in C# is because = is always an assignment operator, and the assignment expression always evaluates to (returns) the value that was assigned. Therefore, in this case, the expression y = 5 not only assigns the value 5 to the variable y, but it also evaluates to the value of 5 as well. So, when you set x to the value of that expression, it gets set to 5 as well. In VB, however, the result is very different:

Dim y As Integer
Dim x As Integer = y = 5

In VB, the compiler will assume that the expression y = 5 is an equality test, so it will evaluate to False. Therefore, it will attempt to set x = False which may or may not work depending on the value of Option Strict.

Steven Doggart
  • 43,358
  • 8
  • 68
  • 105
6

Here's how the above code works. The right hand side evaluates simply to true or false, hence the equivalence (==) operator. That value is then set using the assignment (=) operator.

Another example where both operators are used (although differently) is in file IO:

while((line = streamReader.ReadLine()) != null)
{
   //do file IO
}
kmarks2
  • 4,755
  • 10
  • 48
  • 77
  • 1
    That's not a semantically equivalent example. The OP's example assigns the result of a boolean expression to a variable. Your example performs an assignment and then tests the assigned value against null. – Ed S. May 18 '12 at 20:38
  • 1
    Agreed, and the OP should take note of that. I figured it couldn't hurt to show the OP another scenario where both of these operators get used in one place. – kmarks2 May 18 '12 at 20:40
  • perhaps its not exact, but the OP asked about a statement having both an assignment and an comparison operator. Its certainly a relevant example. – Kyle Trauberman May 18 '12 at 20:40
  • @KyleTrauberman: Sure, I don't think it's irrelevant, but perhaps a bit confusing to a beginner as it is different, but the post does not call attention to that fact (it actually says "another example", making it seem like they are the same thing). – Ed S. May 18 '12 at 20:42
5

The rvalue is evaluated before the assignment takes place. The rvalue is an equality comparison. The result of a comparison is a boolean true or false, which can of course be assigned to a bool.

It's the same as saying

if((File.GetAttributes(path) & FileAttributes.Directory)
             == FileAttributes.Directory)
{
    isDir = true;
}
else
{
    isDir = false;
}

But is more concise.

It's not some special-case of assignment and equality in the same statement. You could do something like

bool bar, baz, qux;
bar = qux = false;
baz = true;
bool foo = (bar || baz || qux); // foo is true

foo becomes true if any of the flags bar, baz, or qux is true. You can evaluate any expression in an rvalue.

sorpigal
  • 25,504
  • 8
  • 57
  • 75
3

= is an assigment operator, it is setting the value of isDir

== is a comparison operator, and is checking to see if the values on either side are equal

Kyle Trauberman
  • 25,414
  • 13
  • 85
  • 121
msmucker0527
  • 5,164
  • 2
  • 22
  • 36
2

== is an operator which returns a boolean in C#. isDir is being assigned the result of that operator. This is not restricted to C#, but is not necessarily common to all .net languages (for instance, as far as I know VB .net still uses single equals for equality testing).

Kyle Trauberman
  • 25,414
  • 13
  • 85
  • 121
Tim
  • 1,011
  • 6
  • 12
1

This statement is getting the attributes for the file path (with is a flags enum) ANDing that with the enum value for directory (this essentially wipes all the bits of the enum to 0 except for the one that represents FileAttributes.Directory. It then compares the result of that operation to see if it is actually equal to the enum value representing FileAttributes.Directory. The result of that operation is then stored in the isDir variable.

This code is equivalent to:

FileAttributes pathAttributes = File.GetAttributes(path);
FileAttributes checkForDirectory = pathAttributes & File.GetAttributes(path);
bool isDir = checkForDirectory == FileAttributes.Directory;

For more information about how flag enums work (which is what FileAttributes is) see: Enums

Kyle Trauberman
  • 25,414
  • 13
  • 85
  • 121
MgSam
  • 12,139
  • 19
  • 64
  • 95