我从未见过以这种方式初始化的for
循环,并且不明白为什么会以这种方式编写?
我正在研究如何在.NET中连接到IMAP服务器,并开始查看名为ImapX的库中的代码。我在一个方法中找到了for
循环,该方法将数据写入NetworkStream
,然后看起来在时髦的for
循环中读取响应。我不想逐字复制和粘贴其他人的代码,但这里是要点:
public bool SendData(string data)
{
try
{
this.imapStreamWriter.Write(data);
for (bool flag = true; flag; flag = false)
{
var s = this.imapStreamReader.ReadLine();
}
}
catch (Exception)
{
return false;
}
return true;
}
同样,这不是确切的代码,但这是一般的想法。这就是所有方法都做的,它不使用服务器响应,如果没有抛出异常,它只返回true
。我只是不明白for
循环是如何或为何以这种方式使用的;任何人都可以解释初始化这个优惠有什么好处,如果有的话?
答案 0 :(得分:5)
这是一次执行循环的可怕方式。如果您将flag
initalizer更改为并非总是true
,则可能略微更有意义,但不是很多。我之前完全没有建议过这个代码:
Animal animal = ...;
for (Dog dog = animal as Dog; dog != null; dog = null)
{
// Use dog...
}
...作为一种使用as
运算符而不“污染”外部范围的方法。但这是语言愚蠢,而不是我真正使用的东西。
答案 1 :(得分:2)
我以前认为你正在查看原始源代码,但是根据你的评论,听起来你正在看着基于MSIL的Reflector的重构C#。重要的是要理解,这并不一定与所写的原始代码非常相似。
在MSIL级别,没有for
循环或while
循环。只有条件分支指令。 (参见这里:http://weblogs.asp.net/kennykerr/archive/2004/09/23/introduction-to-msil-part-6-common-language-constructs.aspx)任何试图重构C#的工具都必须对代码最初的结构进行一些猜测。似乎很可能这不是最初编写为for
循环,而是Reflector检测到IL 可以由for
循环生成,并且其启发式错误的猜测它应该是for
循环,而不是其他东西。
如果我在ILSpy中查看相同的代码,它将呈现为while
循环。它仍然是多余的,但它看起来不那么奇怪。此外,原始代码可能实际上做了一些已经优化的东西,可能调用[Conditional]
方法或标有#if
指令的代码。然后,也许原来的代码用于做其他事情,但部分被注释掉了 - 评论没有留在IL中。或者也许过去有更多的代码,它只是简单删除。
简而言之,您在Reflector中看到的方法与最初编写的方式有很多不同。您应该将它视为IL的更漂亮的表示,而不是C#的例子,因为它是由人类编写的。
答案 2 :(得分:1)
我将此作为评论,但我想这也是答案。
“循环”毫无意义。它会将flag
初始化为true
,并声明仅在flag
仍为true
时执行。但是,flag
在第一次迭代后显式设置为false
。所以在这种情况下,它保证只运行一次。
我怀疑作者试图确保控制流会在ReadLine()
上暂停 - 但无论如何它都会这样做,直到收到用户输入为止。
答案 3 :(得分:0)
正如其他人所指出的那样,for循环几乎是一种无操作。
但是,它做了一件事,可能会或可能不会重要:它引入了命名空间范围。变量s
的范围是for循环的主体。退出for循环后s
超出范围。您可以通过简单地创建一个块来获得相同的效果,因此:
{
var s = this.imapStreamReader.ReadLine();
}
这仍然很愚蠢。
不知道原作者试图用这个来完成什么 - 也许是为了确保他的s
被摧毁/垃圾收集/处置 - 而不是这种技术会起作用(它不会)