C# 一个语句怎么能同时包含=和==?

C# 一个语句怎么能同时包含=和==?,c#,.net,visual-studio-2010,operators,C#,.net,Visual Studio 2010,Operators,我发现,答案包括以下陈述: bool isDir = (File.GetAttributes(path) & FileAttributes.Directory) == FileAttributes.Directory; 他的问题是关于.net的,我当时正在Visual Studio中用C#net编写代码。在同一语句中同时使用赋值运算符和等于运算符的功能是否适用于所有.net语言,还是特定于某些语言?另外,我能解释一下上面的代码是如何工作的吗?假设path引用了

我发现,答案包括以下陈述:

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

他的问题是关于.net的,我当时正在Visual Studio中用C#net编写代码。在同一语句中同时使用赋值运算符和等于运算符的功能是否适用于所有.net语言,还是特定于某些语言?另外,我能解释一下上面的代码是如何工作的吗?假设
path
引用了一个目录,我希望
isDir
是真的,但是有人能解释为什么吗?

=
是一个在C#中返回布尔值的运算符
isDir
正在分配该运算符的结果。这并不局限于C#,但并非所有.net语言都通用(例如,据我所知,VB.net仍然使用单等于进行相等测试)。

=
运算符执行的相等测试优先于由
=
运算符执行的赋值。因此,如果
=
运算符的两侧相等,则
isDir
变量将设置为
true
,否则将设置为
false
。换句话说,这相当于说:

if ((File.GetAttributes(path) & FileAttributes.Directory) == FileAttributes.Directory)
    isDir = true;
else
    isDir = false;
这在VB.NET中是可能的。我不能用其他语言回答。在VB.NET中,等效值为:

Dim isDir As Boolean = ((File.GetAttributes(path) And FileAttributes.Directory) = FileAttributes.Directory)
由于VB对赋值运算符和相等性测试运算符使用相同的字符(
=
),因此它根据上下文确定要执行的操作。VB编译器非常聪明,知道第一个
=
操作符是赋值,第二个是相等测试。然而,这显然令人困惑,因此出于可读性的考虑,通常不鼓励这样做。对于有其他语言背景的人来说,这尤其令人困惑。例如,在C#中,可以执行以下操作将两个变量设置为相同的值:

int y;
int x = y = 5;  // Both x and y will be set to 5
在C#中发生的原因是
=
始终是赋值运算符,赋值表达式的计算结果总是(返回)赋值的值。因此,在这种情况下,表达式
y=5
不仅将值5分配给变量
y
,而且还计算为值5。因此,当您将
x
设置为该表达式的值时,它也会设置为5。但是,在VB中,结果非常不同:

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

在VB中,编译器将假定表达式
y=5
是一个相等测试,因此它将计算为
False
。因此,它将尝试设置
x=False
,这取决于
选项Strict
的值,这是上述代码的工作方式。右侧的计算结果仅为true或false,因此使用等价(=)运算符。然后使用赋值(=)运算符设置该值

使用两个运算符(尽管不同)的另一个示例是在文件IO中:

while((line = streamReader.ReadLine()) != null)
{
   //do file IO
}

=
是一个分配运算符,用于设置isDir的值


=
是一个比较运算符,正在检查两边的值是否相等

在赋值之前对右值进行求值。右值是一个相等比较。比较的结果是布尔值true或false,这当然可以指定给布尔值

这等于说

if((File.GetAttributes(path) & FileAttributes.Directory)
             == FileAttributes.Directory)
{
    isDir = true;
}
else
{
    isDir = false;
}
但更为简洁

这不是同一个语句中赋值和相等的特殊情况。你可以这样做

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

如果任何标志
bar
baz
qux
为真,则
foo
变为真。您可以对右值中的任何表达式求值。

此语句获取文件路径的属性(带有标志枚举)以及目录的枚举值(这实际上会将枚举的所有位擦除为0,但表示
FileAttributes.Directory
的位除外。然后,它会比较该操作的结果,以查看它是否实际等于表示
FileAttributes.Directory
的枚举值。然后,该操作的结果存储在isDir变量中

此代码相当于:

FileAttributes pathAttributes = File.GetAttributes(path);
FileAttributes checkForDirectory = pathAttributes & File.GetAttributes(path);
bool isDir = checkForDirectory == FileAttributes.Directory;
有关标志枚举如何工作(即FileAttributes是什么)的更多信息,请参阅:

你肯定写过像布尔数RequalsFive=num==5这样的代码,不是吗?@KirkWoll:我怀疑。如果(num==5)someBool=true;else someBool=false;@vittor:很多初学者(甚至一些“有经验的”开发人员…)都会写
我真的不明白布尔表达式和布尔类型。我不明白,但这是事实。@vittore因为这里的每个人都曾在某一点上沉迷于编码。这就是为什么会得到答案。为了帮助这个人。我们不必为此沾沾自喜。@Kirk当然不明白。我总是这样写:
boolean NumberqualsFive=(num==5)
几个额外的括号不会伤害任何人,特别是当它们有助于确保代码对未来的维护人员来说是可读且明确的时候!这不是一个语义等价的示例。OP的示例将布尔表达式的结果赋给变量。您的示例执行赋值,然后根据null。同意,OP应该注意这一点。我认为向OP展示另一个场景不会有什么坏处,在这个场景中,这两个运算符都在一个地方使用。也许这不准确,但OP询问的是一个既有赋值运算符又有比较运算符的语句。这当然是一个相关的示例。@KyleTrauberman:当然,我不认为这是正确的不相关,但对初学者来说可能有点困惑,因为这是不同的,但这篇文章并没有引起人们对这一事实的注意(它实际上说的是“另一个例子”,让人觉得它们是一样的)。