Qué problema tiene este código? (III)

Continuando con la línea de posts relacionada con problemas potenciales con los que los programadores .NET deben tener cuidado, aquí va uno al que, si se tratara de un film, le añadiríamos la coletilla “basado en una historia real”: deriva directamente de un bug que encontré hace unos días revisando el código de un proyecto heredado.

Suponga que tenemos una clase como la siguiente:

public class Customer
{
    public Guid Id { get; set; }
    public string Name { get; set; }

    public Customer(string name)
    {
        Id = Guid.Empty;
        Name = name;
    }

    public void Persist()
    {
        // Here the object is persisted to the database
        // And ‘Id’ field is assigned a value if it is Empty
    }

    // …More class’ definition…

    public void Action()
    {
        if (Id == null)  // The bug is here!
            Persist();
        // The action’s code…
    }
}

¿Ve dónde está el problema? Seguramente de manera inconsciente, el programador comparó el Guid (que, como sabemos, es un tipo valor) con null en vez de con Guid.Empty. Como resultado, el objeto no se persiste si no lo estaba anteriormente (la comparación produce siempre falso).

En este excelente post, miembros del equipo de C# explican claramente por qué la comparación (de igualdad o desigualdad) de un tipo valor con null produce una advertencia y no un error; básicamente, debido a la posibilidad de promoción (lifting) de los tipos valor a sus correspondientes tipos valor anulables. Con eso estoy totalmente de acuerdo; con lo que no lo estoy del todo es con la asignación a este problema potencial del nivel de advertencia 2, con lo que pasará totalmente desapercibido en caso de que el proyecto se compile con nivel 1.

Como siempre, ¡queda advertido!

Octavio Hernandez

Desarrollador y consultor en tecnologías .NET. Microsoft C# MVP entre 2004 y 2010.

2 comentarios en “Qué problema tiene este código? (III)

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *