C#: IDE, por favor, no me "ayudes" más... (III)
Tags: spanish, csharp, programming, discuss
Published: 2023-12-27 13:27:07

---
title: C#: IDE, por favor, no me "ayudes" más... (III) 
published: true
series: ¿El IDE ayuda?
description: Cuando tu IDE quiere que uses "var" en todas tus variables locales.
tags: #spanish #csharp #programming #discuss
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2023-12-27 12:25 +0000
---

Como siempre, quiero recordar que los IDE's, sobre todo en aspectos como la refactorización, son una gran ayuda en la programación.

Lo que veremos en este pequeño artículo es cómo el IDE nos pone nerviosos si no utilizamos *var*. Esta partícula es una simple ayuda al tecleo (teclear menos) en las declaraciones de variables locales, es decir, dentro de un método, como se puede ver en el siguiente esquema.

    <lvalue> = <rvalue>

Mientras *lvalue* es el nombre de una variable cuando la asignamos por primera vez, *rvalue* es una expresión. Esto quiere decir que puede ser un literal, como 5, "hola", o 3.5; o puede ser el resultado de llamar a un método.

En el siguiente ejemplo podemos ver varias asignaciones:

```c#
int x = 0;
const decimal pi = 3.1416;
string nombre = "Baltasar";
int sentidoDeLaVida = 42;
```

En los ejemplos más arriba, estamos creando una variable y asignándole un valor en el momento. Es muy importante recordar que el tipo del *rvalue* debe ser el mismo que el tipo del *lvalue* (al margen de algunas conversiones numéricas implícitas, como de **double** a **int**, por ejemplo).

...y a continuación, podemos ver cómo "quedaría" el resultado si utilizaramos *var*:

```c#
var x = 0;
const double pi = 3.1416;
var nombre = "Baltasar";
var sentidoDeLaVida = 42;
```

No ha cambiado mucho el código. No podemos aplicar *var* a constantes, eso es verdad. Pero en cuanto al resto, lo que va a hacer el compilador es asignar a cada una de las variables el tipo del *rvalue*. En este ejemplo, 0 es un **int**, por lo que el tipo de *x* será **int** (si en lugar de 0 tecleáramos 0.0 o 0d, entonces será **double**, com 0m sería **decimal**...); como "Baltasar" es una cadena de caracteres, *nombre* será un **string**, y en cuanto al *sentidoDeLaVida*, pues bueno, es 42, por lo que su tipo es **int**.

Cuando a la derecha del operador de asignación ('=') tenemos un literal, entonces estamos en uno de esos casos "obvios" en los que podemos utilizar *var* sin miedo. A no ser, claro, que queramos "restringir" el tipo de la variable con respecto al literal.

```c#
var y = 0.1;
var z = 0.2;
```

En este caso, *x* va a ser una variable **double**, si queremos que sea un **float**, entonces tendremos que utilizar el tipo de la variable a la izquierda, o un sufijo de tipo a la derecha.

```c#
var y = 0.1f;
float z = 0.2;
```

Pero ahora veamos un caso en el que no tenemos un literal a la derecha, sino una expresión basada en llamar a un método o propiedad.

```c#
class Chart: Control {
    // ...

    void NormalizeData()
    {
        var numValues = this._values.Count;
        var maxValue = this._values.Max();

        // ...
    }
}
```

¡Rápido! ¿Cuál es el tipo de *numValues* y de *maxValue*?

Veamos, en el caso de *numValues* obtenemos el resultado de la propiedad *Count*, de un objeto que probablemente es una colección. Es probable, por tanto, que *numValues* sea de tipo **int**. En cuanto a *maxValue*, se trata de el valor máximo de la colección anterior. Puesss... no sé, espera, que me desplazo a la declaración de *_values*.

```c#
class Chart: Control {
    // ...
    private readonly List<int> _values;
}
```

Ah, bien, entonces *maxValue* es un **int**.

¿Qué problema tiene esto?

Pues que utilizando *var* hemos perdido la posibilidad de reconocer el tipo de la variable de un solo vistazo. Hemos tenido que realizar varias deducciones para llegar a la conclusión buscada en cuanto a los tipos de las variables.

¿Es importante poder reconocer y entender el código de un vistazo? Sí, lo es y mucho. Recordemos que todas las empresas que se dedican a la programación (Microsoft, IBM...), reconocen que los programadores se pasan al menos el 50% del tiempo (cuando este porcentaje no sube al 60 o incluso el 70%), leyendo código. El código sufre de modificaciones contínuas, bien sea por la resolución de *bugs* o por la adición de nueva funcionalidad.

Sé lo que estás pensando. Sí, hay código que no se modifica: el que no se usa. Si has creado una aplicación de cualquier tipo y no recibes peticiones de ampliación de funcionalidad o de resolución de errores, es que nadie la está usando.

Vale, cerramos [el libro gordo de Petete](https://es.wikipedia.org/wiki/Petete).

En cuanto a **Rider**, nos subraya las variables locales que no han sido declaradas con *var*. Pareciera que *var* es obligatorio. [No lo es](https://learn.microsoft.com/es-es/dotnet/csharp/language-reference/statements/declarations#implicitly-typed-local-variables). Solo es una herramienta.

Pero para ser justos, **Rider** también nos proporciona una ayuda visual que nos indica precisamente el tipo de la variable en cuestión.

```c#
class Chart: Control {
    // ...
    private void NormalizeData()
    {
        var numValues: int = this._values.Count;
        var maxValue: int = this._values.Max();

        // ...
    }
}
```

¿Soluciona esto el problema? En mi opinión no, o solo parcialmente. Nos lleva la información del tipo a la derecha de la variables, cuando esperamos verlo a la izquierda (históricamente, C comenzó esta "tradición" que ha continuado con C++, Java o C#). Además, no siempre vamos a editar código con **Rider**. Y en este caso, las ayudas desaparecerán (no es texto, no forman parte del código fuente).

Entonces, ¿cuando es correcto utilizar *var*? En realidad, es simple: cuando el tipo a la derecha del igual es obvio, o incluso se repite. Veamos unos cuantos casos en el siguiente código de ejemplo.

```c#
var sentidoDeLaVida = 42;
var xGap = (int) ( (double) this.GraphWidth / ( numValues + 1 ) );
var valores = new List<int>( numValores );
```

En realidad, es el último caso del ejemplo más arriba para el que se creó *var*: para no tener que repetir el tipo de la expresión a la derecha también a la izquierda. En otro caso, sería como aparece a continuación.

```c#
List<int>? valores = new List<int>( numValores );
```

Ese '?' es importante: *var* siempre asume que la variable siendo declarada (*valores*, en este caso) siempre es anulable (*nullable* en inglés). Dicho de otra forma, que a *valores* se le va a poder asignar *null* en algún momento de su vida. Si no deseamos esto comportamiento, entonces tendremos que repetir el tipo a la izquierda y a la derecha. Recuerda que en estos casos el código será mucho más flexible si seguimos la costumbre de utilizar una interfaz a la izquierda.

```c#
IList<int> valores = new List<int>( numValores );
```

(Continuará...)