Search code examples
c#initializationoperatorscomma-operator

What are the mechanics of the comma operator/separator while setting an int in C#?


I was analyzing a code sample in the accepted answer of this stackoverflow question, which contains this block of code:

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
        }
    }
}

And the following line threw me for a loop:

int remaining = chunkSize, bytesRead;

It is my understanding that, unlike many C++ operators, the comma operator was deliberately left out of the C# specification; yet, the code above compiles and runs just fine.

I know that you can declare multiple comma-separated variables like so:

int i, j, y;

and even set them

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

But the line in question appears in a while loop and contains one variable that is (hopefully) already declared and initialized chunkSize, as well as one that gets set in a nested while loop below bytesRead. so the usage of the comma as a separator in a multiple variable declaration doesn't really make sense to me.

In the above C# code, what are the mechanics and behavior of the comma operator/separator? Also, is there a place in the specification where these things are defined?


Solution

  • This is defining two variables.

    int remaining = chunkSize, bytesRead;
    

    is equivalent to

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

    It's a bit of a code smell to me because multiple declarations in the same line are hard to follow and might give an impression that there is ANY connection between remaining and bytesRead even though there isn't.

    bytesRead is set to a value in the line below (input.Read), but somehwere the compiler needs to know that bytesRead is an int. And C# allows uninitialized variables to be declared in a method, as long as you're initializing it somehwere before trying to use it.