Search code examples
c#goto

Is this goto expressive?


The following code was a proof of concept for a message batching routine. Do I avoid goto like the plague and rewrite this code? Or do you think the goto is an expressive way to get this done?

If you'd rewrite please post some code...

var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
    byte[] buffer = null;
    try
    {
        socket.Recv(out buffer);
    }
    catch
    {
        // ignore the exception we get when the socket is shut down from another thread
        // the connected flag will be set to false and we'll break the loop
    }

HaveAnotherMessage:
    if (buffer != null)
    {
        try
        {
            var item = TraceItemSerializer.FromBytes(buffer);
            if (item != null)
            {
                queue.Enqueue(item);

                buffer = null;
                if (queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
                {
                    goto HaveAnotherMessage;
                }
            }
        }
        catch (Exception ex)
        {
            this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
            this.tracer.TraceException(TraceEventType.Error, 0, ex);
        }
    }

    // queue processing code
}

Solution

  • Replace the goto with a do-while, or simply a while loop if you don't want the "always run once" functionality you have right now.

    var queue = new Queue<TraceItem>(this.batch);
    while (this.connected)
    {
        byte[] buffer = null;
        try
        {
            socket.Recv(out buffer);
        }
        catch
        {
            // ignore the exception we get when the socket is shut down from another thread
            // the connected flag will be set to false and we'll break the loop
        }
    
        do {
            if (buffer != null)
            {
                try
                {
                    var item = TraceItemSerializer.FromBytes(buffer);
                    if (item != null)
                    {
                        queue.Enqueue(item);
                        buffer = null;
                    }
                }
                catch (Exception ex)
                {
                    this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
                    this.tracer.TraceException(TraceEventType.Error, 0, ex);
                }
            }
        } while(queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
    
        // queue processing code
    }