C# Snabbreferens
  • C# snabbreferens
  • Lathund: Skapa projekt
  • Lathund: koda i konsolen
  • Lathund: koda i WPF
  • Kompilering och publicering
  • Externa resurser
  • Grundläggande
    • Datatyper […]
      • String
      • Tuples
      • Enum
    • Fel
    • Typkonvertering
    • Operatorer
    • Boolska satser
    • Konsolen (Console)
    • If-satser
    • Loopar
    • Listor och arrayer
    • Slump (Random)
    • Strings
    • Metoder
    • Använda bibliotek (using)
    • Delegates, events och lambdas
    • Matematik (Math)
    • Vektorer (Numerics)
    • Datum och tid
    • Try-catch och Exception
    • Namngivning
    • Begrepp
    • Reference vs value types
    • Projektstruktur
    • Dotnet i terminalen
  • Filhantering
    • Filsökvägar
    • Läsa och skriva
    • Filer och mappar
    • Open, close, using
    • Serialisering […]
      • JSON-serialisering
      • XML-serialisering
    • Resursfiler
    • Filformat
      • JSON
  • Klasser och objektorientering
    • Översikt objektorientering
    • Lathund för klassdesign
    • Klasser och instanser
    • Struct
    • Public, private och protected
    • Klassdiagram
    • Klassmetoder
    • Konstruktorer
    • Arv
    • Komposition
    • Inkapsling och properties
    • Static
    • Polymorfism […]
      • Virtual, override
    • Generiska klasser
    • Abstract
    • Interface
    • Attribut
  • Annat
    • RayLib […]
      • Raylib setup
      • Fönster i Raylib
      • Grundläggande grafik
      • Geometriska former
      • Bilder och texturer
        • Texture
        • Image
      • Input
      • Text
      • Rectangle
      • Kollisioner
      • Kamera
      • Ljud
      • Raylib-CSharp*
    • MonoGame […]
      • Monogame-projekt*
      • MCGB Editor*
      • Input*
      • Grafik*
      • Kollisioner
      • Ljud*
    • Nätverk och internet […]
      • CRUD, HTTP och REST
      • URL:er och REST
      • RESTful client*
      • Thunder
      • RESTful server (Minimal API)
        • Swagger och OpenAPI
      • RESTful server (Web API) […]
        • Controllers
        • Models/dataklasser
        • Tester med RESTer
    • Linq
      • Linq-metoder
      • Linq-queries
    • Databaser
      • SQLite-kommandon
      • SQLite och VSCode
      • C# och SQLite
      • Entity Framework Core
    • Threading
      • Thread
      • Task
    • Pseudokod och diagram
    • Windows UI
      • WPF
      • XAML*
      • WinUI*
  • Mjukvara
    • Dotnet SDK
    • Visual Studio Code […]
      • Extensions
      • Inställningar
      • Debugging
      • Snabbkommandon
      • Snippets
      • Felsökning
    • Git & GitHub […]
      • Git-begrepp
    • Andra verktyg
  • Tekniker
    • Begränsa input
    • Game states
    • Gå igenom en array (eller lista)
    • Länkade listor och andra strukturer
    • Ta bort saker ur listan man går igenom
    • 2D-spelbräden
    • Timers
  • CONTRIBUTING
Powered by GitBook
On this page
  • Action
  • Dictionary med Actions
  • Func
  • Anonyma metoder i delegatvariabler
  • Multicasting: delegat-variabler med flera metoder
  • Events
  • Lambdas

Was this helpful?

  1. Grundläggande

Delegates, events och lambdas

OBS: Lite överkurs =)

Delegates är ett sätt att kunna göra så att variabler pekar mot metoder istället för mot värden eller objekt i minnet. De är lite överkurs, men ganska användbara.

// Skapar en delegate som passar in på metoder som 
// inte tar emot några parametrar eller returnerar något.
delegate void Task(); 

// En metod som passar in på delegaten
static void SayHello() {
  System.WriteLine("Hello!");
}

static void Main(string[] args)
{
  Task t = SayHello; // Lagra en referens till SayHello-metoden i "t"
  t(); // Att köra t som en metod är nu samma sak som att köra SayHello.
}

När man skapar en delegat så beskriver den en metodprofil. Man kan säga att varje delegat beskriver en kategori av metoder.

// Stämmer in på metoder som tar emot en int-parameter och inte returnerar något.
delegate void DelegateOne(int y);

// Stämmer in på metoder som returnerar en int utan att ta emot några parametrar.
delegate int DelegateTwo();

// Stämmer in på metoder som returnerar en float efter att ha tagit emot
// en string och en int.
delegate float DelegateThree(string x, int y);

När man skapat sin delegat används den alltså som om den vore en datatyp. När man lagrar metoderna i den så ser man till att inte använda () efter metodnamnet, för då körs ju metoden istället, innan tilldelningen.

DelegateOne test = MethodOne;

Action

En Action är en generisk delegat som passar in på metoder som inte returnerar ett värde. Om man vill matcha metoder som tar emot parametrar kan dessa anges mellan <>.

static void Hello()
{
  Console.WriteLine("Hello");
}

static void HelloTo(string target)
{
  Console.WriteLine($"Hello {target}");
}

Action example1 = Hello;
Action<string> example2 = HelloTo

example1();
example2("Micke");

Dictionary med Actions

Ett exempel på hur man kan använda delegater.

Dictionary<string, Action> actions = new Dictionary<string, Action>();

actions.Add("first", DoFirst);
actions.Add("second", DoSecond);
  
actions["first"](); // Kör DoFirst-metoden


static void DoFirst()
{
  /* .. */
}

static void DoSecond()
{
  /* .. */
}

Func

Func är en generisk delegat som matchar metoder som returnerar något. En eller flera datatyper anges inom <>. Anges flera så är den sista alltid returtypen, resten är parametrar.

static int Addition(int a, int b)
{
  return a + b;
}

static string MakeStrengthString(int str)
{
  return $"Strength: {str}";
}

Func<int, int, int> math = Addition;

Func<int, string> statDisplay = MakeStrengthString;

int y = math(3,4);

string strength = statDisplay(14);

Anonyma metoder i delegatvariabler

Anonyma metoder saknar eget namn.

static void Main(string[] args)
{
  Action t = delegate()
    {
      System.WriteLine("Hello!");
    }
    
  t();
}

De är praktiska när man aldrig faktiskt kommer att anropa metoden med dess eget namn, utan bara vill kunna lägga in den i en variabel eller en lista.

Dictionary<string, Action> actions = new Dictionary<string, Action>();

actions.Add("greet", 
  delegate ()
  {
    Console.WriteLine("Hello");
  }
);

actions["greet"]();

Multicasting: delegat-variabler med flera metoder

Action multiCaster = delegate() { Console.WriteLine("Hello"); };

multiCaster += delegate() { Console.WriteLine("World"); };

multiCaster(); // Skriver först ut Hello, sedan World
Action good = delegate() { Console.WriteLine("Good"); };

Action bye = delegate() { Console.WriteLine("Bye"); };

Action morning = delegate() { Console.WriteLine("Morning"); };

Action goodMorning = good + morning;
Action goodBye = good + bye;

goodMorning(); // Skriver ut "Good" och "Morning"
goodBye(); // Skriver ut "Good" och "Bye"

Att lägga till en metod till en multicast-delegat kallas subscribing, och att ta bort en metod från en multicast-delegat kallas unsubscribing.

Events

Nackdelen med multicast-delegater är att den som har tillgång till dem inte bara kan lägga till nya metoder i dem, utan också aktivera dem och göra större ändringar – som att till exempel ändra dem till null.

Med en event kan den som har tillgång utifrån bara lägga till och ta bort metoder (subscribe/unsubscribe)

Events kan bara existera i klasser, och de kan bara anropas (invoke) inifrån den klassen

Avatar.cs
public class Avatar
{
  public event Action OnDeath; // OBS: nyckelordet "event"

  public Avatar()
  {
    OnDeath += DeathMessage; // Subscribe:a klassmetoden DeathMessage
  }

  public void Update()
  {
    OnDeath.Invoke(); // Aktivera (invoke) eventet
  }

  public void DeathMessage() { Console.WriteLine("YOU DIED"); }
}
Program.cs
Avatar p = new Avatar();

Action PauseGame = delegate() { Console.WriteLine("Game is paused"); };

// Subscribe:a den lokala metoden PauseGame till eventet OnDeath
p.OnDeath += PauseGame;

p.Update(); // Kör Update-metoden, som i sin tur invoke:ar eventet

Lambdas

Lambda-uttryck är, enkelt uttryckt, ett sätt att skriva väldigt enkla anonyma metoder (anonyma delegater) vars returvärden är direkta resultat av deras parametrar. Ett lambda-uttryck består av en parentes där den anonyma metodens parametervärden anges, en => och slutligen en enkel uträkning som motsvarar det som ska returneras från metoden.

Uträkningen kan bytas ut mot ett kodblock som returnerar ett värde, om mer omfattande

// Delegat som passar alla metoder som tar emot två int-parametrar och
// som returnerar en int som resultat
delegate int Calculation(int x, int y);

static void Main(string[] args)
{
  // Lambda-uttrycket => har två inputs på vänster sida, 
  // och uträkningen på höger sida resulterar i en int.
  // Därför passar lambda-uttrycket in på delegaten Calculation.
  Calculation c = (xInput, xOutput) => xInput * xOutput;

  int result = c(10, 5);
  
  // Detta gör samma sak som ovan, men med ett kodblock istället 
  // för en ren beräkning
  Calculation c2 = (xInput, xOutput) => {return xInput * xOutput};
}

Lambdas används väldigt ofta när man till exempel vill filtrera en lista på något sätt.

List<int> numbers = new List<int>() {2,3,4,5,6};

// FindAll returnerar en lista med alla föremål i listan som matchar ett visst
// kriterium. Kriteriet ska vara utformat som en metod, som tar emot ett
// föremål av rätt datatyp som parameter och returnerar en bool.
// lambda-uttrycket nedan tar emot en input på vänster sida (n) och uttrycket
// på höger sida är en boolsk jämförelse.
// Därför kommer lowNumbers att innehålla en lista med alla integers från
// numbers, som är < 4.
List<int> lowNumbers = numbers.FindAll(n => n < 4);

De kan också användas till events och till multicast-delegates. Ofta används detta när det bara är ganska lite kod som ska köras.

Avatar p = new Avatar();

p.OnDeath += () => Console.WriteLine("Game is paused");
PreviousAnvända bibliotek (using)NextMatematik (Math)

Last updated 2 years ago

Was this helpful?

Om man vill att flera metoder ska köras när en delegat-variabel anropas så kan man kombinera delegater för att skapa s.k. .

multicast-delegater