C#: atestat și pregătire ONTI

C#: evenimente și notificarea schimbărilor din model

Folosește un eveniment C# pentru a anunța schimbarea scorului. Înțelege abonarea, dezabonarea și diferența dintre o notificare și o comandă a interfeței.

Într-un quiz, scorul poate fi afișat în mai multe locuri: un label, un raport și un jurnal. Modelul nu trebuie să cunoască fiecare ecran. El anunță că scorul s-a schimbat, iar obiectele interesate se abonează. Evenimentul este o notificare despre o schimbare deja validată, nu o cerere adresată interfeței să repare starea.

Cum lucrezi cu exemplul

Programul complet folosește C# 7.3 și API-uri disponibile în .NET Framework 4.8. Deschide Lesson.csproj din arhivă sau creează un proiect Console App (.NET Framework 4.8) și înlocuiește Program.cs. Datele de demonstrație sunt incluse în cod.

Descarcă sursele și instrucțiunile.

Ideea și pașii de implementare

ScoreChangedArgs transportă noua valoare. ScoreBoard verifică punctajul, actualizează totalul și apoi invocă evenimentul. O variabilă locală reține lista de abonați pentru apel. În acest exemplu toate apelurile sunt sincrone și se fac pe același fir; event nu introduce automat un fir nou.

Abonarea cu += adaugă un handler. Dezabonarea cu -= cere aceeași instanță de delegat. De aceea păstrăm handler-ul într-o variabilă. Dacă te abonezi de două ori, aceeași reacție poate fi executată de două ori. Într-o interfață, leagă evenimentele într-un singur loc: Designer sau constructor, nu accidental în ambele.

Exemplu și rezultat așteptat

Adăugăm zece puncte, apoi cinci. Handler-ul afișează Scor: 10 și Scor: 15. După dezabonare adăugăm încă două puncte: totalul devine 17, dar nu mai apare o notificare. Ultima linie, Final: 17, dovedește că dezabonarea oprește observarea, fără să oprească modelul.

Schemă pentru lecția 6: Add(10); Total devine 10; ScoreChanged(10); Abonat: afișează 10.Add(10) → Total devine 10 → ScoreChanged(10) → Abonat: afișează 10.Mărește schema ↗

Codul complet

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Globalization;
using System.Xml.Linq;
using System.Data;
class ScoreChangedArgs : EventArgs {
    public int Value { get; private set; }
    public ScoreChangedArgs(int value) { Value = value; }
}
class ScoreBoard {
    public int Total { get; private set; }
    public event EventHandler<ScoreChangedArgs> Changed;
    public void Add(int points) {
        if (points < 0) throw new ArgumentOutOfRangeException("points");
        Total = checked(Total + points);
        var handler = Changed;
        if (handler != null) handler(this,new ScoreChangedArgs(Total));
    }
}
class Program {
    static void Main() {
        var score = new ScoreBoard();
        EventHandler<ScoreChangedArgs> show = (sender,e) => Console.WriteLine("Scor: " + e.Value);
        score.Changed += show; score.Add(10); score.Add(5);
        score.Changed -= show; score.Add(2); Console.WriteLine("Final: " + score.Total);
    }
}

Rezultatul programului:

Scor: 10
Scor: 15
Final: 17

Greșeli și limite

Un obiect de viață lungă poate păstra în memorie un formular prin delegatul abonat. Dezabonează formularele când nu mai au nevoie de notificări. Nu actualiza controale Windows Forms dintr-un handler invocat pe un fir de fundal; firul pe care rulează abonatul este cel al invocării. În aplicația de aici notificăm numai după o modificare reușită, astfel încât observatorii să nu afișeze o stare respinsă.

Exersează

Abonează doi handleri, unul pentru text și unul care numără notificările. După două modificări numărul trebuie să fie doi. Dezabonează doar primul și verifică faptul că al doilea continuă. Introdu o valoare negativă: metoda trebuie să refuze operația, totalul să rămână neschimbat și numărul notificărilor să nu crească. Prezice aceste trei rezultate înainte de rulare.

Continuă parcursul

Parcursul complet de 50 de lecții

Bazele C#

Lecția precedentă: C#: separă stocarea printr-o interfață repository

Lecția următoare: C#: resurse, căi relative și tratarea erorilor de fișier.

Referință: documentația Microsoft.

Întrebări frecvente

Evenimentul rulează automat în fundal?

Nu. Handlerii rulează sincron pe firul care invocă evenimentul, dacă nu adaugi explicit alt mecanism.

De ce se execută Click de două ori?

O cauză frecventă este abonarea duplicată, în Designer și în constructor.

Când anunț schimbarea?

După validare și actualizarea completă a stării, nu înaintea unei operații care poate fi refuzată.

Un pas mai departe

Autentifică-te pentru a păstra progresul în cont.

Exersează cu o problemă →