在 C# 中设置 int 时,逗号运算符/分隔符的机制是啥?

Posted

技术标签:

【中文标题】在 C# 中设置 int 时,逗号运算符/分隔符的机制是啥?【英文标题】:What are the mechanics of the comma operator/separator while setting an int in C#?在 C# 中设置 int 时,逗号运算符/分隔符的机制是什么? 【发布时间】:2018-07-16 17:58:43 【问题描述】:

我正在分析此*** question 的已接受答案中的代码示例,其中包含以下代码块:

public static void SplitFile(string inputFile, int chunkSize, string path)

    const int BUFFER_SIZE = 20 * 1024;
    byte[] buffer = new byte[BUFFER_SIZE];

    using (Stream input = File.OpenRead(inputFile))
    
        int index = 0;
        while (input.Position < input.Length)
        
            using (Stream output = File.Create(path + "\\" + index))
            
                int remaining = chunkSize, bytesRead;
                while (remaining > 0 && (bytesRead = input.Read(buffer, 0,
                        Math.Min(remaining, BUFFER_SIZE))) > 0)
                
                    output.Write(buffer, 0, bytesRead);
                    remaining -= bytesRead;
                
            
            index++;
            Thread.Sleep(500); // experimental; perhaps try it
        
    

下面一行让我陷入了循环:

int remaining = chunkSize, bytesRead;

据我了解,与许多 C++ 运算符不同,逗号运算符被故意排除在 C# 规范之外;然而,上面的代码编译并运行得很好。

我知道你可以像这样声明多个逗号分隔的变量:

int i, j, y;

甚至设置它们

int i = 0, j = 1, y = 2;

但有问题的行出现在 while 循环中,并且包含一个(希望)已经声明和初始化的变量 chunkSize,以及一个在 bytesRead 下面的嵌套 while 循环中设置的变量。所以在多变量声明中使用逗号作为分隔符对我来说真的没有意义。

在上面的 C# 代码中,逗号运算符/分隔符的机制和行为是什么?另外,规范中有没有定义这些东西的地方?

【问题讨论】:

您没有在脑海中正确解析语句。您正确地注意到您可以在声明中使用逗号分隔的变量列表,并且您正确地注意到您可以选择在声明中分配初始值。您还可以混合匹配这两种语法!您可以拥有一个以逗号分隔的声明列表,其中其中一些具有初始化程序,这就是您所拥有的。 现在,这是一个有趣的问题:这是什么意思:var x = 10, y = 123.4;。这是否意味着:int x = 10; double y = 123.4; 还是意味着 double x = 10, y = 123.4;。看看你能不能弄明白,然后试试看。你说对了吗? 这与VB中一个著名的设计问题有关,你可以说Dim Curly, Larry, Moe as Stooge,当然这意味着:CurlyLarryVariantMoe是@987654336 @,这很令人困惑。 @EricLippert 我真的很想念你在编码方面的精彩冒险! 感谢您的客气话。我只是最近没有时间写博客。我希望能重回正轨! 【参考方案1】:

这是定义两个变量。

int remaining = chunkSize, bytesRead;

等价于

int remaining = chunkSize;
int bytesRead; // uninitialized, gets set to bytesRead = input.Read(buffer,... below

这对我来说有点代码味道,因为同一行中的多个声明很难遵循,并且可能会让人觉得 remainingbytesRead 之间存在任何联系,即使没有联系。

bytesRead 被设置为下面一行中的一个值 (input.Read),但是编译器需要知道 bytesRead 是一个 int。而且 C# 允许在方法中声明未初始化的变量,只要您在尝试使用它之前对其进行了初始化。

【讨论】:

天哪,我不敢相信他们允许这样做。阅读起来非常混乱,尤其是如果您以前从未见过。 @LewsTherin 是的,虽然我猜这可能只是解析器工作方式的副作用? int x, y, z(三个未初始化的整数)和int x = 0, y = 1, z = 2 都是有效的,所以我猜可能没有人考虑过禁止int x = 0, y, z = 2, v, i, j = 5 @LewsTherin 现在,var 不允许使用它,即使初始化程序匹配。 var x = 10, y = 20 导致 CS0819 Implicitly-typed variables cannot have multiple declarators @EricLippert 老实说,我也不知道那条线做了什么,这就是我启动 LINQPad 并对其进行测试的原因。冒着听起来像推销员的风险,但购买许可证值得一百万倍,因为任何时候我都想知道“这会做什么?它甚至会起作用吗?”我可以快速启动 linqpad 并在 30 秒内得到答案,而不是猜测。 (另外,像 Path.GetExtension 这样的东西是否包含点,或者其他可以通过运行一些实际代码轻松测试的东西)。 在设计该功能时,我对读者进行了调查,我们还对 MVP、Microsoft 内部人员等进行了调查,以了解 var x = 10, y = 123.4; 的“明显”语义应该是什么,以及大约是50-50,这是“明显”的意思。所以我们把它定为非法的。一个“方便”的功能总是让一半的专业人士使用它,这是一个糟糕的功能! blogs.msdn.microsoft.com/ericlippert/2006/06/27/…【参考方案2】:

我还认为在同一行中声明多个变量会让人感到困惑和代码异味,尽管语言允许其他东西。

为了在 C# 布局约定中支持这一点,link 声明:

每行只写一个声明。

【讨论】:

以上是关于在 C# 中设置 int 时,逗号运算符/分隔符的机制是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL 的 INT 列中输入逗号分隔的字符串

批处理,如何在for 中的 delims 中设置空格和其他字符做分隔符

如何在 multiDatesPicker 中设置选定的日期

在 C# 中设置 USB 键盘状态

流动客户端主题时如何在 C# HttpClient 中设置 OIDC/OAuth 不记名令牌

C# SaveFileDialog 从多个扩展名中设置一个在未键入扩展名时自动添加扩展名