În prezent, codifică un simplu strat de acces la date și mă întrebam ce tip trebuie să expun celorlalte straturi.
I am going to internally implement the Data as a List<>, but I remember reading something about not exposing the List type to the consumers if not needed.
public List GetAllUsers()//non C# users: that means List of User :)
Știți de ce (google nu a ajutat)? Ce vă expuneți de obicei pentru astfel de lucruri? IList? IEnumerable?
Usually it's best to expose the least powerful interface that the user can still meaningfully work with. If the user just needs some enumerable data, return IEnumerable
. If that's not enough because the user needs to be able to modify the list (attention! shouldn't often be the case), return an IList
.
Joel întreabă o întrebare validă în comentariul său: De ce, într-adevăr, expuneți interfața cea mai puțin puternică în locul acordării puterii maxime a utilizatorului? (Parafrazat)
Ideea din spatele acestui lucru este că metoda returnând datele ar putea să nu se aștepte ca utilizatorul să-și modifice conținutul: O altă metodă a clasei ar putea aștepta ca lista să nu fie goală după ce o referință la ea a fost returnată. Imaginați-vă că utilizatorul elimină toate datele din listă. Cealaltă metodă trebuie să facă o verificare suplimentară, care ar putea să nu fie necesară.
Mai important, acest lucru expune părți din implementarea internă prin intermediul tipului de returnare. Dacă am nevoie să modificăm implementarea în viitor, astfel încât să nu mai folosească un container IList
, am o problemă: fie trebuie să schimb contractul de metode, introducând o schimbare de performanță. Sau trebuie să copiez datele într-un container.
Ca exemplu, imaginați-vă că o implementare eficientă utilizează un Dicționar și returnează colecția Values
care nu implementează IList
.
Cu siguranta este ceva Ceva. Folosind o interfață veți reduce cuplarea și veți face mai ușor schimbarea detaliilor implementării stratului de date pe drum. Care interfață depinde de circumstanțe. IList este bun, dar uneori este posibil să aveți nevoie de funcționalitate ICollection sau doriți să specificați valori care sunt ReadOnly.
Ar trebui să vă gândiți cu atenție înainte de a reveni la IEnumerable. Dacă codul de bază utilizează "randament" pentru a genera IEnumerable sau folosește LINQ, atunci veți ține în evidență toate resursele utilizate.
Ar trebui să copiați IEnumerable într-un alt IEnumerable înainte de ao returna. Folosind IList, faceți acest lucru o cerință, astfel încât nimeni să nu poată întoarce din greșeală un IEnumerable.
Pe de altă parte, întoarcerea unui IList implică apelantului că poate schimba lista returnată.