Extensión de interfaces y genéricos
Añada comportamiento a muchos tipos a la vez.
Extensión de interfaces y genéricos es una lección gratuita de C# Academy en CoddyKit. Esta es la lección 2 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.
Extender interfaces
Puede escribir un método de extensión cuyo parámetro this sea una interfaz. Todos los tipos que implementen la interfaz obtienen el método al instante. Así es exactamente como LINQ añade decenas de métodos a IEnumerable<T>.
Una extensión genérica para IEnumerable
Al hacer que el método sea genérico con respecto a T y extender IEnumerable<T>, la utilidad funciona con cualquier secuencia: listas, arrays, resultados de consultas y mucho más.
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static bool IsEmpty<T>(this IEnumerable<T> source)
{
foreach (var item in source) return false;
return true;
}
}
public class Program
{
public static void Main()
{
var nums = new List<int> { 1, 2, 3 };
Console.WriteLine(nums.IsEmpty());
Console.WriteLine(new int[0].IsEmpty());
}
}Iterar la secuencia
Dentro de la extensión, trate el parámetro como cualquier IEnumerable<T>. Aquí calculamos una suma sin depender de LINQ.
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static int SumValues(this IEnumerable<int> source)
{
int total = 0;
foreach (var n in source) total += n;
return total;
}
}
public class Program
{
public static void Main()
{
var nums = new List<int> { 10, 20, 30 };
Console.WriteLine(nums.SumValues());
}
}Devolver una secuencia nueva
Las extensiones también pueden devolver secuencias. Combinadas con yield return, se convierten en operadores perezosos al estilo de LINQ.
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static IEnumerable<T> EveryOther<T>(this IEnumerable<T> source)
{
bool take = true;
foreach (var item in source)
{
if (take) yield return item;
take = !take;
}
}
}
public class Program
{
public static void Main()
{
var letters = new List<string> { "a", "b", "c", "d", "e" };
foreach (var l in letters.EveryOther())
Console.WriteLine(l);
}
}Restricciones de tipos genéricos
Puede restringir el parámetro genérico para exigir determinadas capacidades. Aquí, where T : IComparable<T> nos permite comparar elementos para encontrar el máximo.
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static T MaxItem<T>(this IEnumerable<T> source) where T : IComparable<T>
{
bool started = false;
T best = default;
foreach (var item in source)
{
if (!started || item.CompareTo(best) > 0) { best = item; started = true; }
}
return best;
}
}
public class Program
{
public static void Main()
{
var nums = new List<int> { 3, 9, 1, 7 };
Console.WriteLine(nums.MaxItem());
}
}Extender una interfaz personalizada
Sus propias interfaces también se benefician. Defina una interfaz y, después, incorpore el comportamiento compartido mediante extensiones en lugar de duplicarlo en cada implementación.
using System;
public interface INamed { string Name { get; } }
public class Dog : INamed { public string Name => "Rex"; }
public static class NamedExtensions
{
public static string Greeting(this INamed n) => "Hello, " + n.Name;
}
public class Program
{
public static void Main()
{
var d = new Dog();
Console.WriteLine(d.Greeting());
}
}Varios parámetros de tipo
Las extensiones pueden ser genéricas con respecto a varios parámetros de tipo. Este auxiliar de proyección transforma una secuencia mediante una función, de forma muy similar a Select de LINQ.
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static IEnumerable<TResult> Map<TSource, TResult>(
this IEnumerable<TSource> source, Func<TSource, TResult> f)
{
foreach (var item in source) yield return f(item);
}
}
public class Program
{
public static void Main()
{
var nums = new List<int> { 1, 2, 3 };
foreach (var s in nums.Map(n => "#" + n))
Console.WriteLine(s);
}
}Combinar con LINQ integrado
Sus métodos de extensión coexisten con LINQ. Puede encadenar su operador personalizado con operadores estándar en una única canalización fluida.
using System;
using System.Collections.Generic;
using System.Linq;
public static class EnumerableExtensions
{
public static IEnumerable<T> EveryOther<T>(this IEnumerable<T> source)
{
bool take = true;
foreach (var item in source) { if (take) yield return item; take = !take; }
}
}
public class Program
{
public static void Main()
{
var nums = Enumerable.Range(1, 10);
var result = nums.Where(n => n > 2).EveryOther().ToList();
Console.WriteLine(string.Join(", ", result));
}
}Extender IEnumerable abarca muchos tipos
Dado que los arrays, las listas, los diccionarios, los conjuntos hash y los resultados de consultas implementan IEnumerable<T>, una sola extensión cubre todos estos tipos a la vez.
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static int CountItems<T>(this IEnumerable<T> source)
{
int n = 0;
foreach (var item in source) n++;
return n;
}
}
public class Program
{
public static void Main()
{
Console.WriteLine(new[] { 1, 2, 3 }.CountItems());
Console.WriteLine(new HashSet<string> { "a", "b" }.CountItems());
}
}Por qué este patrón es escalable
Las extensiones de interfaces proporcionan auxiliares polimórficos sin herencia. Escriba la lógica una sola vez contra la interfaz y todos sus implementadores, tanto actuales como futuros, la obtendrán automáticamente.
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static string JoinWith<T>(this IEnumerable<T> source, string sep)
{
return string.Join(sep, source);
}
}
public class Program
{
public static void Main()
{
var nums = new List<int> { 1, 2, 3 };
Console.WriteLine(nums.JoinWith(" -> "));
}
}Pruébelo usted mismo
Construya un pequeño operador genérico sobre IEnumerable<T> y encadénelo con LINQ. Observe cómo funciona con cualquier tipo de secuencia.
using System;
using System.Collections.Generic;
using System.Linq;
public static class EnumerableExtensions
{
public static IEnumerable<T> WithoutDuplicatesByKey<T, TKey>(
this IEnumerable<T> source, Func<T, TKey> keySelector)
{
var seen = new HashSet<TKey>();
foreach (var item in source)
if (seen.Add(keySelector(item))) yield return item;
}
}
public class Program
{
public static void Main()
{
var words = new[] { "apple", "avocado", "banana", "cherry", "blueberry" };
var firstPerLetter = words.WithoutDuplicatesByKey(w => w[0]);
Console.WriteLine(string.Join(", ", firstPerLetter));
}
}Comprobación rápida
Piense en cómo se declaran las extensiones al estilo de LINQ.
Recapitulación
Extender interfaces, especialmente IEnumerable<T>, es la base de la programación al estilo de LINQ.
- Haga que el método sea genérico y use la interfaz como tipo de
this. - Use
yield returnpara crear operadores perezosos. - Aplique restricciones
wherepara exigir capacidades comoIComparable<T>. - Una sola extensión de interfaz cubre todos sus implementadores, incluidos los futuros.
Preguntas frecuentes
¿La lección «Extensión de interfaces y genéricos» es gratis?
Sí — el texto completo de «Extensión de interfaces y genéricos» 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 «Extensión de interfaces y genéricos»?
Añada comportamiento a muchos tipos a la vez. 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 2 de 4.
¿Cuánto tiempo toma la lección «Extensión de interfaces y genéricos»?
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
- Definición de métodos de extensión
- Extensión de interfaces y genéricos
- Resolución de métodos de extensión
- Diseño de buenas extensiones