Generisk matematik (översikt) och generiska attribut (vid behov)
Emulera generisk matematik utan moderna funktioner: skicka en ops-provider eller delegates, begränsa typer noggrant och simulera "generic attributes" via Type-parametrar.
Generisk matematik (översikt) och generiska attribut (vid behov) är en gratis lektion i C# Academy på CoddyKit. Detta är lektion 2 av 3. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för C# Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i C# Academy innehåller totalt 3 lektioner.
Generisk matematik i C# 6
Mål: Skriva numeriska algoritmer generiskt i C# 6.
- Det finns inga statiska abstrakta operatorer på T
- Alternativ: ett gränssnitt för ops-provider eller små delegater
- Använd attribut med Type-parametrar för annoteringar
Mönstret ops-provider
Tillhandahåll Zero och Add via ett gränssnitt. Den generiska algoritmen anropar dessa metoder i stället för att använda + på T.
using System;
using System.Collections.Generic;
public interface INumericOps<T>
{
T Zero { get; }
T Add(T a, T b);
}
public sealed class IntOps : INumericOps<int>
{
public int Zero { get { return 0; } }
public int Add(int a, int b) { return a + b; }
}
public sealed class DoubleOps : INumericOps<double>
{
public double Zero { get { return 0.0; } }
public double Add(double a, double b) { return a + b; }
}
public class Program
{
static T Sum<T>(IEnumerable<T> items, INumericOps<T> ops)
{
T acc = ops.Zero;
foreach (T x in items) acc = ops.Add(acc, x);
return acc;
}
public static void Main(string[] args)
{
int s1 = Sum(new int[] {1,2,3}, new IntOps());
double s2 = Sum(new double[] {1.5, 2.0}, new DoubleOps());
Console.WriteLine("Sum int = " + s1);
Console.WriteLine("Sum double = " + s2);
}
}
Medelvärde med hjälpmetoder
För operationer som inte kan uttryckas generiskt, till exempel division, skickar man med en liten konverterare eller en extra delegat.
using System;
using System.Collections.Generic;
public interface INumericOps<T>
{
T Zero { get; }
T Add(T a, T b);
}
public sealed class DoubleOps : INumericOps<double>
{
public double Zero { get { return 0.0; } }
public double Add(double a, double b) { return a + b; }
}
public class Program
{
static double Average<T>(IEnumerable<T> items, INumericOps<T> ops, Func<T,double> toDouble)
{
T acc = ops.Zero;
int count = 0;
foreach (T x in items) { acc = ops.Add(acc, x); count++; }
if (count == 0) throw new ArgumentException("Empty sequence", "items");
// convert with a delegate for division
return toDouble(acc) / count;
}
public static void Main(string[] args)
{
double avg = Average<double>(new double[] {2.0, 4.0, 6.0}, new DoubleOps(), delegate(double d) { return d; });
Console.WriteLine("Avg = " + avg);
}
}
Delegatbaserad fold
Delegater håller lösningen minimal: skicka med ett startvärde och en kombineringsfunktion. Det passar bra för små verktygsmetoder.
using System;
public class Program
{
static T Fold<T>(T[] xs, T seed, Func<T,T,T> combine)
{
T acc = seed;
for (int i = 0; i < xs.Length; i++) acc = combine(acc, xs[i]);
return acc;
}
public static void Main(string[] args)
{
int sum = Fold<int>(new int[] {1,2,3}, 0, delegate(int a, int b) { return a + b; });
double sumD = Fold<double>(new double[] {1.5, 2.5}, 0.0, delegate(double a, double b) { return a + b; });
Console.WriteLine("Sum ints = " + sum);
Console.WriteLine("Sum doubles = " + sumD);
}
}
Alternativ för attribut
Det finns inga äkta generiska attribut i C# 6. Skicka en Type till attributet för att ange den relaterade generiska typen.
using System;
using System.Reflection;
// C# 6 cannot declare generic attributes. Workaround: pass a Type.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class ValidatorForAttribute : Attribute
{
public Type TargetType { get; private set; }
public ValidatorForAttribute(Type targetType) { TargetType = targetType; }
}
public sealed class Customer { public string Name; }
[ValidatorFor(typeof(Customer))]
public sealed class CustomerValidator
{
public bool IsValid(Customer c) { return c != null && !string.IsNullOrEmpty(c.Name); }
}
public class Program
{
public static void Main(string[] args)
{
Type t = typeof(CustomerValidator);
object[] attrs = t.GetCustomAttributes(typeof(ValidatorForAttribute), false);
if (attrs.Length > 0)
{
ValidatorForAttribute a = (ValidatorForAttribute)attrs[0];
Console.WriteLine("Validator targets: " + a.TargetType.Name);
}
}
}
Tips och val
Tips:
- Föredra en ops-provider för återanvändbara numeriska algoritmer.
- Använd delegater för små hjälpmetoder (kombinera, konvertera).
- Skicka Type i attribut och läs värdet via reflection för annoteringar.
Lösning för generisk matematik
Sammanfattning
Sammanfattning: Utan modern generisk matematik skickar man med ops eller delegater till algoritmerna. För annoteringar används attribut som innehåller en Type, som sedan läses via reflection.
Lär dig C# med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 93
- Lektioner
- 346
Vanliga frågor
Är lektionen ”Generisk matematik (översikt) och generiska attribut (vid behov)” gratis?
Ja – hela texten till ”Generisk matematik (översikt) och generiska attribut (vid behov)” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i C# Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i C# Academy innehåller totalt 3 lektioner.
Vad lär jag mig i ”Generisk matematik (översikt) och generiska attribut (vid behov)”?
Emulera generisk matematik utan moderna funktioner: skicka en ops-provider eller delegates, begränsa typer noggrant och simulera "generic attributes" via Type-parametrar. Ni övar på C# Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig C# Academy?
Du behöver inga förkunskaper. Utbildningen i C# Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 3.
Hur lång tid tar lektionen ”Generisk matematik (översikt) och generiska attribut (vid behov)”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här C# Academy-lektionen?
Ja. Varje C# Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- unmanaged, notnull, new() (C# 6-emulering)
- Generisk matematik (översikt) och generiska attribut (vid behov)
- Återanvändbara generiska verktyg