Udvidelse af interfaces og generics
Tilføj funktionalitet til mange typer på én gang.
Udvidelse af interfaces og generics er en gratis C# Academy-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i C# Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. C# Academy-kurset indeholder 4 lektioner i alt.
Udvidelse af grænseflader
Du kan skrive en udvidelsesmetode, hvis this-parameter er en grænseflade. Alle typer, der implementerer grænsefladen, får straks metoden. Det er præcis sådan, LINQ tilføjer snesevis af metoder til IEnumerable<T>.
En generisk udvidelse af IEnumerable
Ved at gøre metoden generisk over T og udvide IEnumerable<T> virker hjælpefunktionen for enhver sekvens: lister, arrayer, forespørgselsresultater og meget mere.
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());
}
}Gennemløb af sekvensen
I udvidelsen behandler du parameteren som enhver anden IEnumerable<T>. Her beregner vi en sum uden at være afhængige af 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());
}
}Returnering af en ny sekvens
Udvidelser kan også returnere sekvenser. Kombineret med yield return bliver de til dovent evaluerede LINQ-lignende operatorer.
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);
}
}Begrænsninger for generiske typer
Du kan begrænse den generiske parameter, så den skal have bestemte egenskaber. Her gør where T : IComparable<T> det muligt at sammenligne elementer for at finde et maksimum.
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());
}
}Udvidelse af en brugerdefineret grænseflade
Dine egne grænseflader kan også drage fordel af dette. Definér en grænseflade, og tilføj derefter fælles adfærd via udvidelser i stedet for at kopiere den til hver implementering.
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());
}
}Flere typeparametre
Udvidelser kan være generiske med flere typeparametre. Denne hjælpefunktion til projektion afbilder en sekvens ved hjælp af en funktion, omtrent som LINQ Select.
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);
}
}Kombination med indbygget LINQ
Dine udvidelsesmetoder fungerer sammen med LINQ. Du kan kæde din brugerdefinerede operator sammen med standardoperatorer i én sammenhængende behandlingskæde.
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));
}
}Udvidelse af IEnumerable når mange typer
Da tabeller, lister, ordbøger, hashmængder og forespørgselsresultater alle implementerer IEnumerable<T>, dækker én udvidelse dem alle på én gang.
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());
}
}Hvorfor dette mønster skalerer
Grænsefladeudvidelser giver dig polymorfe hjælpefunktioner uden nedarvning. Skriv logikken én gang mod grænsefladen, så får alle typer, der implementerer den, både nuværende og fremtidige, den automatisk.
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(" -> "));
}
}Prøv selv
Byg en lille generisk operator på IEnumerable<T>, og kæd den sammen med LINQ. Læg mærke til, hvordan den fungerer på enhver sekvenstype.
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));
}
}Hurtigt tjek
Tænk over, hvordan LINQ-lignende udvidelser erklæres.
Opsummering
Udvidelse af grænseflader, især IEnumerable<T>, er grundlaget for LINQ-lignende programmering.
- Gør metoden generisk, og brug grænsefladen som
this-typen. - Brug
yield returntil at opbygge dovent evaluerede operatorer. - Brug
where-begrænsninger til at kræve egenskaber somIComparable<T>. - Én grænsefladeudvidelse dækker alle typer, der implementerer den, også fremtidige typer.
Lær C# med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 93
- Lektioner
- 346
Ofte stillede spørgsmål
Er lektionen “Udvidelse af interfaces og generics” gratis?
Ja — hele teksten til “Udvidelse af interfaces og generics” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af C# Academy-kurset, skal du opgradere til CoddyKit PRO. C# Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Udvidelse af interfaces og generics”?
Tilføj funktionalitet til mange typer på én gang. Du øver dig i C# Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på C# Academy?
Der kræves ingen tidligere erfaring. C# Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.
Hvor lang tid tager lektionen “Udvidelse af interfaces og generics”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne C# Academy-lektion?
Ja. Alle C# Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Definition af extension methods
- Udvidelse af interfaces og generics
- Opløsning af extension methods
- Design af gode extensions