Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Från och med C# 14 kan icke-generiska static class deklarationer använda extension block för att deklarera tilläggsmedlemmar. Tilläggsmedlemmar är metoder eller egenskaper och kan verka vara instans- eller statiska medlemmar. Tidigare versioner av C# aktiverar tilläggsmetoder genom att lägga this till som en modifierare i den första parametern för en statisk metod som deklarerats i en statisk klass på den översta nivån.
Blocket extension anger typ och mottagare för tilläggsmedlemmar. Du kan deklarera metoder, egenskaper eller operatorer i deklarationen extension . I följande exempel deklareras ett enda tilläggsblock som definierar en instanstilläggsmetod, en instansegenskap och en statisk operatormetod.
public static class NumericSequences
{
    extension(IEnumerable<int> sequence)
    {
        public IEnumerable<int> AddValue(int operand)
        {
            foreach (var item in sequence)
            {
                yield return item + operand;
            }
        }
        public int Median
        {
            get
            {
                var sortedList = sequence.OrderBy(n => n).ToList();
                int count = sortedList.Count;
                int middleIndex = count / 2;
                if (count % 2 == 0)
                {
                    // Even number of elements: average the two middle elements
                    return (sortedList[middleIndex - 1] + sortedList[middleIndex]);
                }
                else
                {
                    // Odd number of elements: return the middle element
                    return sortedList[middleIndex];
                }
            }
        }
        public static IEnumerable<int> operator +(IEnumerable<int> left, IEnumerable<int> right)
            => left.Concat(right);
    }
}
Definierar extension mottagaren: sequence, som är en IEnumerable<int>. Mottagartypen kan vara icke-generisk, en öppen generisk eller en sluten allmän typ. Namnet sequence finns i omfånget i varje deklarerad instansmedlem i tillägget. Både tilläggsmetoden och egenskapen har åtkomst till sequence.
Alla tilläggsmedlemmar kan nås som om de vore medlemmar av mottagartypen:
IEnumerable<int> numbers = Enumerable.Range(1, 10);
numbers = numbers.AddValue(10);
var median = numbers.Median;
var combined = numbers + Enumerable.Range(100, 10);
Du kan deklarera valfritt antal medlemmar i ett enda block, så länge de delar samma mottagare. Du kan deklarera så många tilläggsblock i en enda klass också. Olika tillägg behöver inte deklarera samma typ eller namn på mottagaren. Tilläggsparametern behöver inte innehålla parameternamnet om de enda medlemmarna är statiska:
extension(IEnumerable<int>)
{
    // Method:
    public static IEnumerable<int> Generate(int low, int count, int increment)
    {
        for (int i = 0; i < count; i++)
            yield return low + (i * increment);
    }
    // Property:
    public static IEnumerable<int> Identity => Enumerable.Empty<int>();
}
Statiska tillägg kan anropas som om de vore statiska medlemmar av mottagartypen:
var newSequence = IEnumerable<int>.Generate(5, 10, 2);
var identity = IEnumerable<int>.Identity;
Operatorer anropas som om de är användardefinierade operatorer för typen.
Viktigt!
Ett tillägg introducerar inte något omfång för medlemsdeklarationer. Alla medlemmar som deklareras i en enda klass, även om de finns i flera tillägg, måste ha unika signaturer. Den genererade signaturen innehåller mottagartypen i dess namn för statiska medlemmar och mottagarparametern för tilläggsinstansmedlemmar.
I följande exempel visas en tilläggsmetod med hjälp av this modifieraren:
public static class NumericSequenceExtensionMethods
{
    public static IEnumerable<int> AddValue(this IEnumerable<int> sequence, int operand)
    {
        foreach (var item in sequence)
            yield return item + operand;
    }
}
Metoden Add kan anropas från vilken annan metod som helst som om den var medlem i IEnumerable<int> gränssnittet:
IEnumerable<int> numbers = Enumerable.Range(1, 10);
numbers = numbers.AddValue(10);
Båda formerna av tilläggsmetoder genererar samma mellanliggande språk (IL). Uppringare kan inte skilja mellan dem. Faktum är att du kan konvertera befintliga tilläggsmetoder till den nya medlemssyntaxen utan att bryta kompatibiliteten. Formaten är både binära och källkompatibla.
Allmänna utvidgningsblock
Var du anger typparametrarna för en tilläggsmedlem som deklareras i ett tilläggsblock beror på var den typparametern krävs:
- Du lägger till typparametern i deklarationen extensionnär typparametern används i mottagaren.
- Du lägger till typparametern i medlemsdeklarationen när typen skiljer sig från valfri typparameter som anges i mottagaren.
- Du kan inte ange samma typparameter på båda platserna.
I följande exempel visas ett tilläggsblock för IEnumerable<T> där två av tilläggsmedlemmarna behöver en andra typparameter.
public static class GenericExtensions
{
    extension<TReceiver>(IEnumerable<TReceiver> source)
    {
        public IEnumerable<TReceiver> Spread(int start, int count)
            => source.Skip(start).Take(count);
        public IEnumerable<TReceiver> Append<TArg>(IEnumerable<TArg> second, Func<TArg, TReceiver> Converter)
        {
            foreach(TReceiver item in source)
            {
                yield return item;
            }
            foreach (TArg item in second)
            {
                yield return Converter(item);
            }
        }
        public IEnumerable<TReceiver> Prepend<TArg>(IEnumerable<TArg> second, Func<TArg, TReceiver> Converter)
        {
            foreach (TArg item in second)
            {
                yield return Converter(item);
            }
            foreach (TReceiver item in source)
            {
                yield return item;
            }
        }
    }
}
Medlemmarna Append och Prepend specificerar den extra typparametern för konverteringen. Ingen av medlemmarna upprepar typparametern för mottagaren.
Motsvarande tilläggsmetoddeklarationer visar hur dessa typparametrar kodas:
public static class GenericExtensions
{
    public static IEnumerable<T> Spread<T>(this IEnumerable<T> source, int start, int count)
        => source.Skip(start).Take(count);
    public static IEnumerable<T1> Append<T1, T2>(this IEnumerable<T1> source, IEnumerable<T2> second, Func<T2, T1> Converter)
    {
        foreach (T1 item in source)
        {
            yield return item;
        }
        foreach (T2 item in second)
        {
            yield return Converter(item);
        }
    }
    public static IEnumerable<T1> Prepend<T1, T2>(this IEnumerable<T1> source, IEnumerable<T2> second, Func<T2, T1> Converter)
    {
        foreach (T2 item in second)
        {
            yield return Converter(item);
        }
        foreach (T1 item in source)
        {
            yield return item;
        }
    }
}
Se även
Språkspecifikation för C#
Mer information finns i C#-språkspecifikationen. Språkspecifikationen är den slutgiltiga källan för C#-syntax och -användning.