Activación y comprensión de NRT
Active el contexto nullable, comprenda los tipos de referencia nullable y non-nullable, y lea las advertencias del compilador.
Activación y comprensión de NRT es una lección gratuita de C# Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C# Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C# Academy incluye 4 lecciones en total.
El error de los mil millones de dólares
Tony Hoare (inventor de null) lo llamó su «error de los mil millones de dólares». En C#, cualquier tipo de referencia podía ser null de forma predeterminada, lo que convertía NullReferenceException en el bloqueo más común en tiempo de ejecución. Los tipos de referencia anulables (NRT) corrigen este problema en el compilador.
Habilitación del contexto de nulabilidad
Habilite NRT globalmente en el archivo del proyecto o por archivo mediante directivas. Una vez habilitado, el compilador trata los tipos de referencia como no anulables de forma predeterminada.
<!-- In .csproj — enable for the whole project -->
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
// Or per-file:
#nullable enable
// ... code with NRT warnings
#nullable disable
// ... code without NRT warningsTipos de referencia no anulables frente a anulables
Con NRT habilitado: string significa que el valor nunca es null, mientras que string? significa que puede ser null. El compilador emite una advertencia si asigna null a un tipo no anulable o desreferencia un valor anulable sin comprobarlo.
#nullable enable
string nonNull = "Hello"; // OK
string? maybeNull = null; // OK — explicitly nullable
nonNull = null; // WARNING: CS8600
Console.WriteLine(maybeNull.Length); // WARNING: CS8602 — may be null
// Fix:
if (maybeNull is not null)
Console.WriteLine(maybeNull.Length); // safeAnálisis de flujo
El compilador realiza un análisis de flujo: sigue el estado de nulabilidad mediante condicionales y ramas, y suprime las advertencias cuando puede demostrar que un valor no es null.
string? name = GetName();
// After null check, name is treated as non-null:
if (name is not null)
Console.WriteLine(name.Length); // no warning
// Same with early return:
if (name is null) return;
Console.WriteLine(name.Length); // no warning — null was returned
// Pattern matching:
if (name is string s)
Console.WriteLine(s.ToUpper()); // no warningAdvertencias de nulabilidad: CS8600–CS8629
Estas son las advertencias de NRT clave que debe comprender: CS8600 (asignación de null a un tipo no anulable), CS8602 (desreferencia de un valor posiblemente null), CS8603 (devolución de null para un tipo no anulable), CS8618 (campo no anulable no inicializado).
#nullable enable
public class Order
{
public string CustomerName { get; set; } // CS8618: not initialized
public string? TrackingNumber { get; set; } // OK — nullable
public Order(string name)
{
CustomerName = name; // now initialized — CS8618 gone
}
}
string? s = GetValue();
Console.WriteLine(s.Length); // CS8602: s might be nullInicialización de campos no anulables
CS8618 se produce cuando un campo o una propiedad no anulable no se establece en el constructor. Soluciones: inicialícelo en la declaración, exíjalo mediante el constructor o use el operador de supresión de null para patrones de DI/ORM.
// Option 1: Initialize in declaration
public string Name { get; set; } = "";
// Option 2: Require via constructor
public class Product
{
public string Name { get; }
public Product(string name) => Name = name;
}
// Option 3: null-forgiving for ORM entities
public string Name { get; set; } = null!;
// null! tells compiler "trust me, this will be set by EF Core"Nulabilidad en tipos genéricos
Los parámetros de tipo genérico se pueden restringir para que no sean anulables. Una restricción where T : notnull garantiza que T nunca pueda ser null.
// Without constraint: T could be nullable
public T? Find<T>(int id) { ... }
// With notnull: T must be a non-nullable type
public T FindRequired<T>(int id) where T : notnull
{
var result = InternalFind<T>(id);
return result ?? throw new KeyNotFoundException();
}
// T? is meaningful only when T is known to be non-nullable
public T? FindOrDefault<T>(int id) where T : class { ... }Nulabilidad en interfaces y sobrescrituras
Al implementar una interfaz o sobrescribir un método, las anotaciones de nulabilidad deben coincidir. El compilador comprueba que las implementaciones sean, como mínimo, igual de no anulables que lo declarado por la interfaz.
public interface IRepository<T>
{
T? FindById(int id); // may return null
T GetOrThrow(int id); // never null
}
// Implementation:
public class ProductRepo : IRepository<Product>
{
public Product? FindById(int id) => _db.Find(id);
public Product GetOrThrow(int id) =>
_db.Find(id) ?? throw new KeyNotFoundException();
}Tipos de valor anulables frente a tipos de referencia anulables
No confunda int? (Nullable<int> — un contenedor de tipo de valor que existía antes de C# 8) con string? (una anotación de NRT, solo en tiempo de compilación y sin sobrecarga en tiempo de ejecución).
// Nullable value type (runtime Nullable<int>)
int? age = null;
bool hasValue = age.HasValue;
int value = age.GetValueOrDefault();
// Nullable reference type (compile-time annotation only)
string? name = null;
// string? has NO runtime wrapper — it's just a compile-time hint
// null check is still needed at runtime
if (name is not null)
Console.WriteLine(name.ToUpper());Supresión de advertencias con !
El operador de supresión de null (!) suprime una advertencia específica de nulabilidad cuando sabe más que el compilador. Úselo con moderación y documente por qué es seguro.
// Use ! when you know the value cannot be null
var user = _db.Users.FirstOrDefault(u => u.Email == email);
var name = user!.Name; // user is guaranteed by business logic
// EF Core navigation properties set by the framework:
public class Order
{
public Customer Customer { get; set; } = null!; // set by EF Core
}Caso real: respuesta de API anulable
Un contenedor de API cuyos campos pueden estar presentes o no en la respuesta JSON; las anotaciones de nulabilidad comunican claramente la intención.
#nullable enable
public class WeatherResponse
{
public string City { get; set; } = ""; // always present
public double Temperature { get; set; } // always present
public string? Description { get; set; } // optional field
public string? AlertMessage { get; set; } // only when there's an alert
}
// Consumer:
var weather = await api.GetWeatherAsync("London");
Console.WriteLine(weather.City); // safe
Console.WriteLine(weather.Description?.ToUpper() ?? "N/A"); // safe null-handlingComprobación rápida
¿Qué sobrecarga en tiempo de ejecución tienen los tipos de referencia anulables (string?) en comparación con los tipos de referencia normales (string)?
Resumen: habilitación y comprensión de NRT
Conclusiones clave:
- Habilítelos globalmente con
<Nullable>enable</Nullable>en .csproj string= nunca es null;string?= puede ser null- El análisis de flujo sigue el estado de null mediante ramas y valores devueltos
- Las anotaciones de NRT solo se aplican en tiempo de compilación, sin sobrecarga en tiempo de ejecución
- CS8618: inicialice los campos no anulables en el constructor o use
= null!para ORM - Use ! con moderación; documente por qué la supresión de null es segura
Preguntas frecuentes
¿La lección «Activación y comprensión de NRT» es gratis?
Sí — el texto completo de «Activación y comprensión de NRT» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C# Academy, actualiza a CoddyKit PRO. El curso de C# Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Activación y comprensión de NRT»?
Active el contexto nullable, comprenda los tipos de referencia nullable y non-nullable, y lea las advertencias del compilador. Practicas C# Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar C# Academy?
No se requiere experiencia previa. C# Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.
¿Cuánto tiempo toma la lección «Activación y comprensión de NRT»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de C# Academy?
Sí. Cada lección de C# Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Activación y comprensión de NRT
- Anotaciones: ?, !, MaybeNull y NotNull
- Operadores null-conditional y null-coalescing
- Migración de una base de código a NRT