Saturday, October 16, 2021 21:45

Cuprins >> LINQ > Semnificația lui „this” în metodele de extensie

Semnificația lui „this” în metodele de extensie

În lecția despre metodele de extensie, am aflat că acestea sunt un mod frumos de a adăuga funcționalitate suplimentară tipurilor deja existente, și am făcut acest lucru prin adăugarea unei metode statice într-o clasă statică, care a luat un parametru de tip, prefixat de cuvântul cheie this, astfel:


Deci, deși clasa mea originală Carte nu conține o metodă numită VindeExemplar(), pot să o apelez în metoda Main() deoarece am declarat o metodă de extensie pentru clasa Carte, iar această metodă statică VindeExemplar() a luat un parametru de tip Carte prefixat de cuvântul cheie this, care semnalează compilatorului că metoda este intenționată ca o metodă de extensie pentru tipul Carte.

Dar de ce cuvântul cheie this? Ce înseamnă, ce reprezintă?

Să recreăm exemplul de mai sus, fără a utiliza o metodă de extensie:

Vizualizează schimbări cod


Legendă:

  • liniile verzi cu un semn plus lângă numerele liniilor sunt linii noi adăugate
  • liniile rosii cu un semn minus lângă numerele liniilor sunt linii vechi șterse




Rezultatul este acesta:

Acum, când instanțiez o nouă Carte în metoda mea Main(), gândiți-vă la ce trebuie să facă operatorul new: trebuie să meargă pe memoria Heap și să aloce suficientă memorie RAM pentru o Carte. Ei bine… cât de mare este o Carte? Dacă ne uităm în interiorul ei, putem vedea că fiecare Carte are propria copie a câmpurilor copiiVandute și titluCarte. Dacă le-am declara ca fiind statice, acestea ar fi împărtășite între toate instanțele de tip Carte, dar nu am făcut-o. Deci, în realitate, o Carte are dimensiunea unui int plus dimensiunea unui string. S-ar putea să vă întrebați despre dimensiunea suplimentară ce trebuie alocată pentru metoda VindeExemplar() a fiecărei instanțe de Carte, însă iată pontul zilei: TOATE METODELE DIN C# SUNT STATICE. Chiar și cele de instanță, unde nu plasăm cuvântul cheie static pe ele, doar arată ca metode de instanță! Acest lucru se datorează faptului că nu are niciun sens pentru compilator când spun new Carte() să facă de fapt o copie a metodei VindeExemplar(), deoarece codul din interiorul acesteia este identic pentru orice instanță de tip Carte. Nu se schimbă de la instanță la instanță.

Vă voi demonstra acest lucru, dar înainte de asta, trebuie să știți că în metodele de instanță, compilatorul vă oferă implicit cuvântul cheie this pentru fiecare membru nestatic pe care îl folosiți. Deci, da, putem scrie metoda VindeExemplar() astfel:

dar compilatorul va adăuga implicit cuvântul cheie this la toți membrii non-statici folosiți în interiorul acesteia:

Dar acum, vom prelua controlul de la compilator și vom transforma VindeExemplar() dintr-o metodă de instanță într-una statică. Desigur, din lecția membrii statici știm deja că nu putem accesa membri de tip instanță în cadrul metodelor statice, așa că trebuie să trimitem și un parametru de tip Carte la metoda VindeExemplar(), pentru a ști la care Carte ne referim :

Vizualizează schimbări cod


Legendă:

  • liniile verzi cu un semn plus lângă numerele liniilor sunt linii noi adăugate
  • liniile rosii cu un semn minus lângă numerele liniilor sunt linii vechi șterse


Evident, în cadrul metodei Main() nu mai pot apela sintactic metoda VindeExemplar() în același mod, trebuie să o apelez prin intermediul clasei în sine, deoarece aparține schiței clasei, nu copiilor sale.

Rezultatul este același:

Deci, sunt doar mai explicită, în loc să mă bazez pe compilator pentru a transmite această instanță, ofer instanța eu însămi. Și din moment ce fiecare instanță Carte are propria copie a membrilor non-statici copiiVandute și titluCarte, dacă ofer instanțe diferite de Carte ca parametri la metoda statică VindeExemplar(), fiecare dintre aceste instanțe va avea copia sa de copiiVandute incrementată, independent una de alta. Pot să creez o altă instanță de tip Carte, să o vând prin aceeași metodă statică și să am în continuare rezultate individuale:

Vizualizează schimbări cod


Legendă:

  • liniile verzi cu un semn plus lângă numerele liniilor sunt linii noi adăugate
  • liniile rosii cu un semn minus lângă numerele liniilor sunt linii vechi șterse



Dacă execut codul acum:

observați cum cartea „Cei trei muschetari” are propria copie de copiiVandute, care este incrementată separat.

Deci, sper că face sens: toate metodele sunt într-adevăr statice, compilatorul doar adaugă cuvântul cheie this pentru noi.

Cu toate acestea, trebuie să recunoașteți, sintaxa pentru vânzarea unei cărți în acest caz nu este chiar frumoasă, pentru că trebuie să spunem Carte.VindeExemplar(primaCarte), în loc să spunem doar primaCarte.VindeExemplar(). Iar aceasta este frumusețea metodelor de extensie, de fapt, acesta este motivul pentru care spunem this Carte în parametrii metodelor de extensie, acesta este motivul pentru care proiectanții limbajului C# au decis să folosească this, deoarece, într-adevăr, acesta este argument this pe care i-l dăm. Dacă modific codul pentru a converti metoda VindeExemplar() într-o metodă de extensie, în continuare pot apela VindeExemplar() ca și cum ar fi o metodă de instanță:

Vizualizează schimbări cod


Legendă:

  • liniile verzi cu un semn plus lângă numerele liniilor sunt linii noi adăugate
  • liniile rosii cu un semn minus lângă numerele liniilor sunt linii vechi șterse



Arată ca o metodă de instanță, se simte ca o metodă de instanță, dar este într-adevăr doar o metodă statică. Iar metodele de instanță fac același lucru, în fundal.

Tags: , , , ,

Leave a Reply



Follow the white rabbit