CodeGym /Kurslar /C# SELF /.NET standart kitabxanasında interfeyslər

.NET standart kitabxanasında interfeyslər

C# SELF
Səviyyə, Dərs
Mövcuddur

1. Əsas interfeyslərin təsnifatı

Əgər düşünürsən ki, interfeyslər — bu, arxitektorlar və "təmiz kod" üçün oyuncaqdır və real işdə onlarsız keçinmək olar, səni təəccübləndirim: C#-da hər hansı ciddi layihə interfeyslərə başdan-ayağa dalır. Niyə? Çünki .NET standart kitabxanasının demək olar ki, hər bir hissəsi interfeyslərlə qurulub! Onlarsız nə kolleksiyalarla işləyə, nə fayl oxuya, hətta LINQ ilə kolleksiyaları filtrləyə bilməzsən.

İnterfeyslər — .NET-də polimorfizm və genişlənmənin təməlidir və məhz onlar bütün framework-un "kublarının" bir-birinə necə birləşdiyini müəyyən edir.

.NET standart kitabxanası sözün əsl mənasında interfeyslərlə doludur. Bu dənizdə batmamaq üçün belə bir təsnifat təklif edirəm (əlbəttə, bu tam deyil — hər şeyi əhatə etməyə ömür çatmaz!):

Kateqoriya İnterfeyslər Nəyə lazımdır?
Kolleksiyalar
IEnumerable
,
IEnumerator
,
IList
,
ICollection
,
IDictionary
Dolaşmaq, dəyişmək, indekslə giriş, açar-dəyər cütləri ilə işləmək
Resurslarla işləmək
IDisposable
Resursların azad olunması (fayllar, bağlantılar, axınlar)
Müqayisə
IComparable
,
IComparer
,
IEquatable
Sıralama, müqayisə, obyektlərin unikalığı
Seriyallaşdırma
ISerializable
Obyektləri bayt axınına çevirmək (və əksinə)
LINQ və sorğular
IQueryable
,
IQueryProvider
Mürəkkəb sorğuların dəstəyi (məsələn, DB-yə)
Asinxronluq
IAsyncEnumerable
,
IAsyncDisposable
Asinxron dolaşma və resursların təmizlənməsi
Hadisələr və bildirişlər
INotifyPropertyChanged
,
INotifyCollectionChanged
Xüsusiyyətlərin/kolleksiyaların dəyişməsinə reaksiya
Tarix və vaxt
IFormattable
Sətirlərin xüsusi formatlanması
Verilənlər strukturları
IStructuralComparable
,
IStructuralEquatable
Kolleksiya və tuple-ların dərin müqayisəsi
Axınlar/giriş-çıxış
IStream
,
IAsyncDisposable
,
IObserver
,
IObservable
Axınlarla işləmək, push/pull-bildirişlər

Vacibdir! Yuxarıda sadalanan interfeyslərin bir çoxunun tip-parametrləri var: List<string>. Adətən bunlar kolleksiyalarda və kolleksiya interfeysləri üçün istifadə olunur Int[] → List<int>. Onları daha ətraflı bir neçə səviyyə sonra, kolleksiyalarla tanış olanda müzakirə edəcəyik.

2. Kolleksiya interfeysləri

IEnumerable və IEnumerator — foreach üçün keçid biletin

.NET-də demək olar ki, hər bir kolleksiya IEnumerable və ya onun generic versiyası IEnumerable<T> interfeysini reallaşdırır. Məhz bu interfeys sənə foreach sehrli sintaksisini işlətməyə imkan verir:

List<int> numbers = new List<int> { 1, 2, 3 };
foreach (int n in numbers) // işləyir, çünki List<int> IEnumerable<int> reallaşdırır
{
    Console.WriteLine(n);
}

Bu interfeys minimal versiyada belə görünür:

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}

IEnumerator — kolleksiyanı "gəzən" interfeysdir, kolleksiyanı addım-addım gəzir:

public interface IEnumerator
{
    bool MoveNext();
    object Current { get; }
    void Reset();
}

Real tapşırıqlarda sən çox tez-tez parametr kimi və ya qaytarılan dəyər kimi IEnumerable<T> istifadə edəcəksən. Məsələn, massivdən bütün cüt ədədləri qaytaran metod:

public IEnumerable<int> GetEvenNumbers(int[] array)
{
    foreach (var x in array)
        if (x % 2 == 0) yield return x;
}

Bəli, yield açar sözü magiya edir — interfeysi sənin əvəzinə reallaşdırır, amma bu barədə sonra daha ətraflı danışacağıq.

ICollection və IList — indekslə giriş və dəyişiklik imkanı olan kolleksiyalar

Əgər sənə sadəcə dolaşmaq yox, element əlavə/çıxarmaq və ya indekslə əldə etmək lazımdırsa, daha ixtisaslaşmış interfeyslər lazımdır:

  • ICollection<T> — Add, Remove metodlarını və Count xüsusiyyətini əlavə edir.
  • IList<T> — əməliyyatların siyahısını genişləndirir, o cümlədən indekslə giriş (this[int index]).
public void PrintFirstItem(IList<string> list)
{
    if (list.Count > 0)
        Console.WriteLine(list[0]);
}

List<T> həm IEnumerable<T>, həm ICollection<T>, həm də IList<T> reallaşdırır. Bu çox rahatdır — onunla həm sadə siyahı kimi, həm də bütün imkanlarla işləyə bilərsən.

IDictionary<TKey, TValue> — "açar-dəyər" cütləri

Əgər sən sözlüklərlə işləməyi sevirsənsə (və bu çox tez-tez olur!), IDictionary<TKey, TValue> interfeysindən istifadə et. O, sənə açarla dəyəri tapmağa və əksinə imkan verir.

public void PrintAllPairs(IDictionary<string, int> ages)
{
    foreach (var pair in ages)
        Console.WriteLine($"{pair.Key}: {pair.Value}");
}

Burada ages istənilən şey ola bilər, istər Dictionary<string, int>, istər SortedDictionary<string, int> — əsas odur ki, bu interfeysi reallaşdırırlar!

3. IDisposable interfeysi: resurslarla düzgün işləmək

Bütün giriş-çıxış, fayllarla, şəbəkə bağlantıları, verilənlər bazası ilə işləmək .NET-də IDisposable interfeysinə bağlıdır. Bu interfeys həyati vacib müqaviləni müəyyən edir: əgər obyektin idarə olunmayan resursları varsa, istifadə bitəndən sonra onu "təmizləmək" lazımdır. Bəli, bu, using sintaksisini mümkün edən oğlandır:

using (StreamReader reader = new StreamReader("file.txt"))
{
    // Faylla işləyirik, using-dən sonra fayl mütləq bağlanır!
    string line = reader.ReadLine();
}

İnterfeysin özü necə qurulub? Gülməli dərəcədə sadədir:

public interface IDisposable
{
    void Dispose();
}

Amma hər bir "ciddi" kitabxana onu reallaşdırır! Bu interfeyslə işləməyin yaxşı təcrübələri barədə daha ətraflı rəsmi sənəddə oxu.

4. Müqayisə və unikalıq üçün interfeyslər

IComparable<T> və IComparer<T>

Əgər istəyirsən ki, obyektlərinin kolleksiyası sıralana bilsin, obyektlər bir-biri ilə müqayisə edə bilməlidir. Bunun üçün IComparable<T> interfeysi var:

public class Student : IComparable<Student>
{
    public string Name { get; set; }
    public int Score { get; set; }

    public int CompareTo(Student? other)
    {
        // Ballara görə azalan sıralama
        if (other == null) return 1;
        return other.Score.CompareTo(this.Score);
    }
}

// İndi tələbələri sıralamaq olar:
var students = new List<Student> { ... };
students.Sort();

Daha ətraflı Microsoft sənədində.

IComparer<T> isə müqayisəni sinifdən kənarda müəyyən etməyə imkan verir — məsələn, bəzən tələbələri ada, bəzən ballara görə sıralamaq istəyirsən:

public class NameComparer : IComparer<Student>
{
    public int Compare(Student? x, Student? y)
    {
        return string.Compare(x?.Name, y?.Name);
    }
}

IEquatable<T> — bərabərlik üçün müqayisə

Obyektinin HashSet<T>-də (yəni kolleksiyalar üçün "unikal" olması) iştirak etməsini istəyirsənsə, IEquatable<T> reallaşdır:

public class Person : IEquatable<Person>
{
    public string Name { get; set; }
    public bool Equals(Person? other)
    {
        if (other == null) return false;
        return this.Name == other.Name;
    }
}

5. Hadisələr və bildirişlər üçün interfeyslər

Heç istəmisən ki, proqramın "bilsin" obyektin xüsusiyyətləri dəyişib? Məsələn, istəyirsən ki, interfeys özü yenilənsin, istifadəçi soyadını dəyişəndə? Məhz bunun üçün INotifyPropertyChanged interfeysi var. O, qrafik interfeysli tətbiqlərdə (məsələn, WPF və ya Xamarin) çox populyardır.

İnterfeysin imzası sadədir:

public interface INotifyPropertyChanged
{
    event PropertyChangedEventHandler? PropertyChanged;
}

Reallaşdırma nümunəsi:

public class User : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    private string name;
    public string Name
    {
        get => name;
        set
        {
            if (name != value)
            {
                name = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
            }
        }
    }
}

İndi bu obyektə istənilən UI bağlaması Name dəyişəndə avtomatik yenilənəcək. Əgər maraqlansan — rəsmi sənədə bax.

6. Digər faydalı interfeyslər

IFormattable interfeysi: çevik formatlama

Obyektinin sətirə gözəl və müxtəlif şəkildə çıxmasını (məsələn, vergüldən sonra fərqli sayda rəqəmlə) istəyirsənsə, IFormattable interfeysini reallaşdır:

public class Temperature : IFormattable
{
    public double Celsius { get; }
    public Temperature(double celsius) => Celsius = celsius;

    public string ToString(string? format, IFormatProvider? formatProvider)
    {
        // Çətinləşdirməyək, sadəcə formata görə 'C' və ya 'F' göstərək
        if (format == "F")
            return $"{Celsius * 9 / 5 + 32} F";
        return $"{Celsius} C";
    }
}

İndi sən temp.ToString("F", null) və ya temp.ToString("C", null) çağırışını edə bilərsən. Buna görə DateTime, double, decimal və digər daxili tiplər çevik formatlamanı dəstəkləyir.

Asinxronluq üçün interfeyslər

C#-da asinxronluq gələndə asinxron dünyada işləmək üçün yeni interfeyslər lazım oldu. Məsələn, obyektin asinxron resursları azad edirsə — IAsyncDisposable reallaşdır:

public interface IAsyncDisposable
{
    ValueTask DisposeAsync();
}

Və indi using əvəzinə await using yazırsan!

Asinxron kolleksiyalarla (await foreach) IAsyncEnumerable<T> interfeysi işləyir, hansı ki, elementləri əsas axını bloklamadan dolaşmağa imkan verir. Onu, məsələn, böyük faylları hissə-hissə oxuyanda və ya internetdən axınla məlumat alanda istifadə edirlər. Daha ətraflı 58-ci səviyyədə :P

Seriyallaşdırma interfeysləri: ISerializable

Tapşırığın obyektləri bayt axınına çevirməkdirsə (məsələn, saxlamaq və ya şəbəkə ilə ötürmək üçün), .NET ISerializable interfeysini təklif edir. Bu, indi o qədər də tez-tez istifadə olunmur, çünki daha rahat mexanizmlər var (məsələn, atributlar və hazır serializer-lər vasitəsilə), amma qeyd etməyə dəyər. İmza nümunəsi:

public interface ISerializable
{
    void GetObjectData(SerializationInfo info, StreamingContext context);
}

7. İnterfeyslərin praktikada tətbiqi: real tətbiq

Tutaq ki, sən kitabxanada kitabların uçotu üçün konsol tətbiqi yazırsan (nə olsun, kimsə etməlidir!). İstəyirsən ki, kitab siyahılarını çıxara, sıralaya, filtrləyə, məlumatları yükləyə və saxlaya biləsən. .NET interfeyslərini bildiyinə görə sən:

  • Fərqli kolleksiya tiplərini IEnumerable<Book> vasitəsilə qaytara bilərsən, istifadəçi düşünməsin ki, bu massivdir, yoxsa siyahı.
  • Fərqli meyarlara görə sıralama əlavə edə bilərsən: IComparable<Book> başlıq üzrə sıralama üçün, ayrıca IComparer<Book> müəllifə görə.
  • Fayllarla işləyərkən resursların effektiv azad olunmasını təmin edə bilərsən IDisposable vasitəsilə.
  • Kitabları janra və ya müəllifə görə filtrləməyi təşkil edə bilərsən LINQ vasitəsilə, hansı ki, IEnumerable<T> reallaşdıran hər şeylə işləyir.
  • Tətbiqi genişləndirə bilərsən — məsələn, fayl saxlama əvəzinə verilənlər bazasına keçə bilərsən, əgər siniflərin interfeyslərlə (IBookStorage) işləyirsə, konkret reallaşmalarla yox.

8. Tipik səhvlər və xüsusiyyətlər

Yeni başlayanların ən yayılmış səhvlərindən biri — dəyişən və metod arqumentlərini interfeyslərlə ("IEnumerable", "IList") yox, konkret reallaşmalarla ("List") elan etməkdir. YADDA SAXLA: əgər "interfeyslərlə proqramlaşdırırsansa", kodun çevik və asan genişlənən olacaq.

Bəzən hansı interfeys səviyyəsini seçəcəyinə diqqət etmək lazımdır — məsələn, metoda sadəcə dolaşmaq lazımdırsa, IEnumerable<T> istifadə et, IList<T> yox, artıq məhdudiyyət qoymamaq üçün.

Daha bir incəlik: əgər sinifdə çoxlu interfeys varsa və onların arasında eyni adlı metod və ya xüsusiyyətlər varsa, interfeysi açıq şəkildə (explicit implementation) reallaşdırmaq lazım olacaq, yoxsa kompilyator başa düşməyəcək.

2
Tapşırıq
C# SELF, səviyyə, dərs
Bağlanıb
IEnumerable interfeysinin yoxlanılması
IEnumerable interfeysinin yoxlanılması
2
Tapşırıq
C# SELF, səviyyə, dərs
Bağlanıb
IComparable interfeysi ilə sıralama
IComparable interfeysi ilə sıralama
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION