Tota aplicació necessita emmagatzemar i manipular dades: el títol d'un llibre, la quantitat de pàgines, si un exemplar està disponible o no. En C#, aquestes dades es desen en variables, i cada variable té un tipus que determina quina mena de valors pot contenir i quines operacions s'hi poden fer. En aquesta lliçó aprendràs a declarar variables, a distingir entre els tipus per valor i els tipus per referència, a convertir dades d'un tipus a un altre, a definir constants, i a entendre l'àmbit (scope) d'una variable. Farem servir sempre dades del catàleg de BiblioTech —títol, ISBN, nombre de pàgines, disponibilitat— com a fil conductor de tots els exemples.

Contingut

  1. Declaració de variables: tipus explícits i var
  2. Tipus per valor
  3. Tipus per referència
  4. Conversió de tipus
  5. Constants: const i readonly
  6. Àmbit de les variables
  7. Valors per defecte i nullability bàsica

Declaració de variables: tipus explícits i var

Declarar una variable en C# significa indicar al compilador tres coses: el seu tipus, el seu nom, i (opcionalment, però recomanable) un valor inicial. La sintaxi general és:

tipus nomVariable = valorInicial;

Per exemple, per representar el títol d'un llibre de BiblioTech:

string titolLlibre = "Cent anys de solitud";
int numeroPagines = 471;
bool estaDisponible = true;

Console.WriteLine(titolLlibre);
Console.WriteLine(numeroPagines);
Console.WriteLine(estaDisponible);

La paraula clau var

El C# també permet declarar una variable fent servir la paraula clau var, deixant que el compilador infereixi (dedueixi) el tipus a partir del valor assignat:

var titolLlibre = "Cent anys de solitud"; // el compilador infereix que es 'string'
var numeroPagines = 471;                  // el compilador infereix que es 'int'
var estaDisponible = true;                // el compilador infereix que es 'bool'

És molt important entendre que var no converteix el C# en un llenguatge de tipat dinàmic: el tipus es continua fixant en temps de compilació, exactament igual que si l'haguéssis escrit de forma explícita; simplement el compilador el dedueix per tu a partir del valor assignat. Per això, un cop declarada amb var, la variable continua "lligada" a aquest tipus:

var numeroPagines = 471;
// numeroPagines = "quatre-centes"; // ERROR: no es pot assignar un string a una variable inferida com a int
Aspecte Tipus explícit (int x = 5;) var (var x = 5;)
Requereix un valor inicial? No Sí, sempre (el compilador necessita el valor per inferir el tipus)
El tipus pot canviar després? No No (un cop inferit, és fix)
Quan usar-lo Quan el tipus aporta claredat en llegir el codi Quan el tipus és obvi pel propi valor, o molt llarg d'escriure

En aquest curs farem servir totes dues formes segons el context; cap és "millor" de forma absoluta, encara que molts equips professionals prefereixen var quan el tipus és evident pel valor assignat (com en els nostres exemples), i el tipus explícit quan ajuda a la claredat.

Tipus per valor

Els tipus per valor (value types) són aquells on la variable conté directament la dada. Quan copies una variable de tipus valor a una altra, es copia la dada completa; cada variable és totalment independent de l'altra. Els tipus per valor més habituals en C# són els numèrics, el booleà i el caràcter:

Tipus Representa Exemple Mida aproximada
int Nombre enter 471 32 bits
long Nombre enter gran 9999999999L 64 bits
double Nombre decimal (coma flotant) 19.99 64 bits
decimal Nombre decimal d'alta precisió 19.99m 128 bits
bool Valor lògic vertader/fals true, false 1 bit (lògic)
char Un únic caràcter 'A' 16 bits

Exemple aplicat a BiblioTech:

int numeroPagines = 471;
double preuLlibre = 24.90;
decimal preuExacte = 24.90m;   // el sufix 'm' indica que es un 'decimal'
bool estaDisponible = true;
char inicialAutor = 'G';

Console.WriteLine(numeroPagines);
Console.WriteLine(preuLlibre);
Console.WriteLine(preuExacte);
Console.WriteLine(estaDisponible);
Console.WriteLine(inicialAutor);

double o decimal?

Tots dos representen números amb decimals, però tenen un ús diferent:

  • double és més ràpid i ocupa menys espai, però pot tenir petites imprecisions en fer certes operacions (per la seva forma interna de representar els números en binari).
  • decimal és més precís, pensat específicament per a càlculs on l'exactitud importa molt, com els diners (per exemple, el preu d'un llibre o una multa per retard a BiblioTech). El seu sufix obligatori és la lletra m al final del número literal.

Com a norma pràctica: per a quantitats de diners, usa sempre decimal; per a la resta de càlculs numèrics amb decimals, double sol ser suficient.

Tipus per referència

A diferència dels tipus per valor, els tipus per referència (reference types) no emmagatzemen la dada directament a la variable, sinó una referència (una mena d'"adreça") que apunta a on està realment emmagatzemada la dada. El tipus per referència més usat, de llarg, és string:

string titolLlibre = "Cent anys de solitud";
string isbn = "978-0307474728";

La diferència pràctica més important entre tipus per valor i per referència apareix en copiar variables:

// Amb un tipus per VALOR (int): cada variable es independent
int paginesLlibreA = 471;
int paginesLlibreB = paginesLlibreA; // es copia el numero
paginesLlibreB = 500;
Console.WriteLine(paginesLlibreA); // continua mostrant 471: no s'ha vist afectada

Amb tipus per referència, veurem al Mòdul 3 (quan treballem amb objectes com Llibre) que dues variables poden apuntar a la mateixa dada en memòria, de manera que modificar-ne una a través d'una variable també afecta el que es veu a través de l'altra. string és un cas particular de tipus per referència que es comporta, a efectes pràctics del dia a dia, de forma molt semblant a un tipus per valor, gràcies a la seva immutabilitat (que estudiarem en detall a la propera lliçó): un cop creada una cadena de text, el seu contingut no es pot modificar; qualsevol operació que "sembli" modificar-la en realitat crea una cadena nova.

Tipus per valor Tipus per referència
Exemples int, double, bool, char, decimal string, arrays, i (Mòdul 3) classes definides per nosaltres
Què conté la variable La dada directament Una referència a la dada, emmagatzemada en un altre lloc de memòria
En copiar una variable Es copia la dada completa (independent) Es copia la referència (totes dues variables poden apuntar a la mateixa dada)

No et preocupis si aquesta distinció no queda del tot clara encara: la retrobarem amb exemples molt més rics quan treballem amb les nostres pròpies classes al Mòdul 3, on les seves implicacions es tornen més visibles.

Conversió de tipus

De vegades necessitem convertir una dada d'un tipus a un altre: per exemple, un nombre de pàgines introduït com a text (string) necessita convertir-se a int abans de poder fer càlculs amb ell. El C# ofereix diverses maneres de fer-ho.

Conversió implícita

Passa automàticament quan no hi ha risc de pèrdua d'informació, per exemple en passar d'un tipus "més petit" a un "més gran":

int numeroPagines = 471;
double numeroPaginesComDecimal = numeroPagines; // conversio implicita: int -> double, sense perdua de dades

Conversió explícita (casting)

És necessària quan pot haver-hi pèrdua d'informació (per exemple, de double a int, on es perden els decimals). S'indica escrivint el tipus destí entre parèntesis:

double preuAmbDecimals = 24.90;
int preuArrodonit = (int)preuAmbDecimals; // conversio explicita: es perd la part decimal (queda en 24)

Convert i Parse/TryParse

La conversió més habitual a la pràctica és convertir text (string) a un tipus numèric, per exemple quan es llegeix una dada introduïda per l'usuari a la consola:

string textNumeroPagines = "471";

// Opcio 1: fent servir la classe Convert
int pagines1 = Convert.ToInt32(textNumeroPagines);

// Opcio 2: fent servir el metode Parse del mateix tipus
int pagines2 = int.Parse(textNumeroPagines);

Console.WriteLine(pagines1);
Console.WriteLine(pagines2);

Totes dues opcions llancen un error en temps d'execució si el text no es pot convertir (per exemple, si conté lletres). Per evitar que el programa s'aturi abruptament davant d'una dada no vàlida, hi ha una alternativa més segura: TryParse.

string entradaUsuari = "quatre-cents"; // un text no numeric, a mode d'exemple

bool conversioCorrecta = int.TryParse(entradaUsuari, out int pagines);

if (conversioCorrecta)
{
    Console.WriteLine($"Nombre de pagines: {pagines}");
}
else
{
    Console.WriteLine("El text introduit no es un numero valid.");
}

TryParse retorna un valor bool indicant si la conversió ha reeixit, i lliura el resultat mitjançant un paràmetre de sortida (out). No et preocupis si la paraula clau out et resulta nova: de moment n'hi ha prou de saber que pagines rebrà el número convertit només si conversioCorrecta és true. Al Mòdul 2, en veure la gestió d'excepcions, entendràs millor per què TryParse sol ser preferible a Parse quan la dada prové d'una font externa (com l'entrada de l'usuari) i no podem garantir que sigui vàlida.

Mètode Comportament davant una dada no vàlida Quan usar-lo
Convert.ToInt32(text) Llança una excepció Quan confies plenament en el format de la dada
int.Parse(text) Llança una excepció Similar a Convert, específic del tipus
int.TryParse(text, out valor) Retorna false, no llança excepció Quan la dada pot no ser vàlida (per exemple, entrada d'usuari)

Constants: const i readonly

No totes les dades han de poder canviar durant l'execució del programa. Quan un valor és fix i conegut de bestreta, és bona pràctica declarar-lo com a constant, per deixar clar que mai canviarà i perquè el mateix compilador impedeixi qualsevol intent accidental de modificar-lo.

const

S'usa per a valors que es coneixen ja en temps de compilació i mai canviaran:

const int MaxLlibresPerSoci = 5;
const string NomSistema = "BiblioTech";

Console.WriteLine($"{NomSistema} permet un maxim de {MaxLlibresPerSoci} llibres per soci.");
// MaxLlibresPerSoci = 10; // ERROR: no es pot modificar una constant

readonly

S'usa, sobretot, en el context de classes (Mòdul 3) per a valors que es fixen una única vegada, normalment en construir l'objecte, però que no es coneixen necessàriament en temps de compilació (per exemple, podrien dependre d'una data o d'una entrada externa). Aquí només el mencionem a mode de comparació; el seu ús real el veurem amb detall al Mòdul 3 quan treballem amb constructors.

const readonly
Es coneix el valor en... Temps de compilació Es pot fixar en temps d'execució (una sola vegada)
On s'usa típicament Variables locals o de classe amb valor fix Membres d'una classe (Mòdul 3)

Àmbit de les variables

L'àmbit (scope) d'una variable és la regió del codi on aquesta variable existeix i es pot utilitzar. En C#, l'àmbit d'una variable local ve determinat pel bloc { } en què es declara:

{
    int numeroPagines = 471; // 'numeroPagines' existeix des d'aqui...
    Console.WriteLine(numeroPagines);
} // ...fins al tancament d'aquest bloc

// Console.WriteLine(numeroPagines); // ERROR: 'numeroPagines' ja no existeix fora del bloc

Aquest comportament es tornarà molt rellevant al Mòdul 2, quan treballem amb blocs d'if i bucles, ja que les variables declarades dins d'aquests blocs no són visibles fora d'ells. De moment, n'hi ha prou de recordar la regla general: una variable viu dins de les claus on va ser declarada, i desapareix en tancar-se aquest bloc.

Valors per defecte i nullability bàsica

Cada tipus per valor té un valor per defecte que rep automàticament si es declara sense inicialitzar explícitament (encara que, a la pràctica, el C# obliga a inicialitzar les variables locals abans d'usar-les, per la qual cosa aquest concepte és més rellevant en altres contextos, com els camps d'una classe que veurem al Mòdul 3):

Tipus Valor per defecte
int, double, decimal 0
bool false
char '\0' (caràcter nul)
string (i altres tipus per referència) null

Què és null?

null representa l'absència d'un valor: una variable de tipus referència (com string) pot no apuntar a cap dada encara. Per exemple, imaginem un llibre de BiblioTech l'ISBN del qual encara no s'ha registrat:

string isbnLlibre = null; // el llibre existeix, pero encara no te ISBN assignat
Console.WriteLine(isbnLlibre is null); // True

El símbol ? per a tipus per valor nullable

Per defecte, els tipus per valor (int, bool, etc.) no poden ser null: sempre tenen un valor concret. Tanmateix, de vegades és útil representar "encara no se sap" fins i tot per a un número, per exemple, el nombre de pàgines d'un llibre que encara no s'ha catalogat completament. Per a això, el C# permet convertir un tipus per valor en nullable afegint el símbol ? després del tipus:

int? numeroPagines = null; // ara si es valid: un 'int?' pot no tenir valor
numeroPagines = 471;       // pero tambe pot tenir un valor normal
Console.WriteLine(numeroPagines);

Això és només una primera presa de contacte amb la idea de nullability; al Mòdul 4 aprofundirem en els tipus de referència nullable (una característica més moderna que estén aquesta mateixa idea a string i altres tipus per referència, ajudant a prevenir errors relacionats amb valors null inesperats). De moment, amb saber que ? després d'un tipus per valor permet representar "sense valor encara" n'hi ha prou.

Errors Comuns i Consells

  • Intentar usar una variable abans d'inicialitzar-la: el C# no permet llegir una variable local que no s'ha inicialitzat; el compilador donarà un error. Sempre assigna un valor inicial (encara que sigui temporal) abans d'usar una variable.
  • Perdre precisió en usar double per a diners: per la seva representació interna en binari, double pot arrossegar petites imprecisions en càlculs amb decimals. Per a preus, multes o qualsevol quantitat monetària, usa sempre decimal.
  • Usar Parse amb dades que poden no ser vàlides: si la dada prové de fora (entrada d'usuari, un fitxer, una API), usa TryParse en lloc de Parse o Convert, per evitar que el programa s'aturi amb un error si la dada no té el format esperat.
  • Confondre const amb una variable normal: un cop declarada una constant, qualsevol intent de modificar-la és un error de compilació; això és intencionat i forma part de la seva utilitat.
  • Consell: quan dubtis entre var i un tipus explícit, pregunta't si el tipus resulta obvi només mirant el valor assignat. Si la resposta és sí, var sol fer el codi més net; si no, el tipus explícit ajuda la persona que llegeixi el codi més endavant.

Exercicis

  1. Declara tres variables per representar un llibre de BiblioTech: el seu títol (string), el seu nombre de pàgines (int) i si està disponible (bool). Fes-ho primer amb tipus explícits i després reescriu les mateixes tres declaracions fent servir var. Imprimeix els tres valors amb Console.WriteLine.

  2. Un usuari introdueix el nombre de pàgines d'un llibre com a text: string entrada = "350";. Escriu codi que converteixi aquest text a int de forma segura fent servir TryParse, i que mostri per consola un missatge diferent segons si la conversió reeix o no. Després, prova a canviar el valor d'entrada per un text no numèric (per exemple, "tres-cents") i comprova que el missatge d'error es mostra correctament.

  3. Declara una constant const int DiesPrestecEstandard = 15; que representi els dies habituals de préstec a BiblioTech. Declara també una variable int? diesExtra = null; que representarà una possible ampliació del préstec, encara no decidida. Escriu el codi necessari per, si diesExtra té un valor assignat, sumar-lo a DiesPrestecEstandard i mostrar el resultat; si no té valor, mostrar només DiesPrestecEstandard. (Pista: pots comprovar diesExtra.HasValue i accedir al valor amb diesExtra.Value, o bé usar l'operador ?? que assigna un valor per defecte quan alguna cosa és null: diesExtra ?? 0).

Solucions

  1. Amb tipus explícits:

    string titolLlibre = "Rayuela";
    int numeroPagines = 635;
    bool estaDisponible = false;
    
    Console.WriteLine(titolLlibre);
    Console.WriteLine(numeroPagines);
    Console.WriteLine(estaDisponible);
    

    Amb var (mateix resultat, tipus inferit automàticament):

    var titolLlibre = "Rayuela";
    var numeroPagines = 635;
    var estaDisponible = false;
    
    Console.WriteLine(titolLlibre);
    Console.WriteLine(numeroPagines);
    Console.WriteLine(estaDisponible);
    
string entrada = "350";

if (int.TryParse(entrada, out int pagines))
{
    Console.WriteLine($"Nombre de pagines registrat: {pagines}");
}
else
{
    Console.WriteLine("El valor introduit no es un nombre de pagines valid.");
}

Si canviem entrada per "tres-cents", TryParse retornarà false i s'executarà la branca de l'else, mostrant el missatge d'error, sense que el programa s'aturi de forma abrupta (a diferència del que passaria amb int.Parse("tres-cents"), que llançaria una excepció).

const int DiesPrestecEstandard = 15;
int? diesExtra = null;

int totalDies = DiesPrestecEstandard + (diesExtra ?? 0);
Console.WriteLine($"Dies totals de prestec: {totalDies}");

diesExtra = 5; // ara si s'assigna una ampliacio
totalDies = DiesPrestecEstandard + (diesExtra ?? 0);
Console.WriteLine($"Dies totals de prestec (amb ampliacio): {totalDies}");

L'operador ?? (anomenat operador de fusió amb null) retorna el valor de l'esquerra si no és null, o el de la dreta en cas contrari. Així, quan diesExtra és null, se suma 0; quan té un valor, se suma aquest valor.

Conclusió

En aquesta lliçó has après a declarar variables amb tipus explícits i amb var, a distingir entre tipus per valor i tipus per referència, a convertir dades d'un tipus a un altre de forma segura, a definir constants, a entendre l'àmbit d'una variable i a fer els teus primers passos amb la nullability bàsica. Tots aquests conceptes són la base sobre la qual es recolzarà absolutament tot el codi que escriguis en els propers mòduls, començant per les classes que definirem al Mòdul 3 (Llibre, Soci, Prestec), que no són més que un conjunt organitzat de variables (anomenades allà "camps" o "propietats") i de comportament associat.

A la propera i última lliçó d'aquest mòdul, Arrays i Cadenes de Text, aprendràs a treballar amb col·leccions de dades (per exemple, diversos títols de llibres a la vegada) fent servir arrays, i a manipular text en profunditat amb la classe string, incloent-hi interpolació, cerques i transformacions habituals.

Curs de Programació en C#

Mòdul 1: Introducció al C#

Mòdul 2: Estructures de Control

Mòdul 3: Programació Orientada a Objectes

Mòdul 4: Conceptes Avançats de C#

Mòdul 5: Treballant amb Dades

Mòdul 6: Temes Avançats

Mòdul 7: Construcció d'Aplicacions

Mòdul 8: Bones Pràctiques i Patrons de Disseny

Mòdul 9: Projecte Final

© Copyright 2026. Tots els drets reservats