Ajutor conversie cod C# .NET în PHP

Din motive ce nu ţin de mine, trebuie să convertesc nişte cod din C#, în PHP, pentru că trebuie să-l modific şi să-l dezvolt.

Nefiind expert C#, am întâlnit o chestie pe care nu ştiu exact cum s-o traduc.

După cum vedeţi, e o clasă banală, prima funcţie e constructorul, evident, iar a doua este o metodă cu 2 parametri.

Dar în a doua funcţie, AddClientInfo, în for, apoi în if, am un CDRSummary, aceeaşi denumire ca şi clasa, dar nu foloseşte this, ci denumirea clasei direct, ca să acceseze o variablă struct şi să-i mai adauge date (ClientInfo este struct).

Ca să nu mă apuc să studiez în detaliu conceptele C#, ce aş putea să înţeleg de aici, se referă la instanţa clasei de fapt, un $this, sau ce anume înseamnă?

Am să ataşez şi clasa întreagă pentru a fi mai uşor de înţeles.

{
	// Token: 0x02000007 RID: 7
	public class CDRSummary
	{
		// Token: 0x06000015 RID: 21 RVA: 0x00003049 File Offset: 0x00001249
		public CDRSummary()
		{
			this.m_PositionEntryList = new CDRSummary.PositionEntry[10];
			this.m_ClientEntryList = new CDRSummary.ClientEntry[10];
			this.Term();
		}

		// Token: 0x06000016 RID: 22 RVA: 0x00003078 File Offset: 0x00001278
		public void AddClientInfo(int clientId, CDRCLInfo info)
		{
			bool flag = false;
			if (clientId >= 0)
			{
				for (int i = 0; i < this.m_nClientCount; i++)
				{
					if (this.m_ClientEntryList[i].ClientId == clientId)
					{
						flag = true;
						CDRSummary.ClientEntry[] clientEntryList = this.m_ClientEntryList;
						int num = i;
						clientEntryList[num].Info = clientEntryList[num].Info + info;
						break;
					}
				}
				if (!flag && this.m_nClientCount < 10)
				{
					this.m_ClientEntryList[this.m_nClientCount].ClientId = clientId;
					this.m_ClientEntryList[this.m_nClientCount].Info = info;
					this.m_nClientCount++;
				}
			}
		}

Eu zic să “traduci” funcţionalitatea, nu să translatezi pur şi simplu dintr-un limbaj în altul. De altfel, e destul de prost codul ăla, parcă e scris de un licean care abia a început să înveţe Turbo Pascal :slight_smile:

1 Like

Păi asta încerc să fac, să înţeleg ce face.

Nu e prima clasă care o traduc, şi multe le-am redus de la ce erau iniţial, la jumate sau sfert ca număr de linii, şi cu exact aceeaşi funcţionalitate.

Dar nu-mi dau seama exact ce vor să facă la faza aia, că nici n-au iniţializat clasă nouă, nici n-o folosesc pe cea existentă, mă gândesc că e ceva truc din C# ce nu înţeleg exact ce ar face.

Dacă te referi la new CDRSummary.PositionEntry[10], cel mai probabil instanţiază un array format din 10 obiecte de tip PositionEntry. Este absurd. De ce în 2018 te-ai limita la array-uri fixe? Cel mai probabil cel care a scris codul habar n-avea că există posibilitatea de a avea array-uri de dimensiuni oarecare. Nici variabila m_nClientCount nu are vreun sens, pentru că este suficient să verifici dimensiunea aray-ului, care în php ar fi count($denumire_array).


Dacă am înţeles bine codul (din fuga calului), cam aşa ar trebui să arate codul, nu e nevoie de nici măcar o iteraţie:

class CDRSummary
{
	private $m_ClientEntryList;
	
	public function __construct()
	{
		$this->m_ClientEntryList = array();
		$this->Term();
	}

	public function AddClientInfo($clientId, $info)
	{
		if($clientId >= 0)
		{
			if(array_key_exists($clientId, $this->m_ClientEntryList))
				$clientEntry = $this->m_ClientEntryList[$clientId];
			else
				$clientEntry = $this->m_ClientEntryList[$clientId] = new ClientEntry;
				
			$clientEntry->Info = $info;
		}
	}
}

Asta vroiam ştiu, de fapt se referă doar la tipul variabilei, care întâmplător se află definită în clasa respectivă.

Codul cred că e vechi, dar sigur e post .net, nu ştiu cine l-a făcut.

Ce face, la esenţă, este că parsează un string, care de fapt e într-un anumit format custom. Acel string de fapt e un log care reprezintă event-uri dintr-o convorbire în voip (inbound callcenter).

Această clasă ia acel string, şi îl parsează ca să afle cine a răspuns, când a răspuns, după cât timp, cât timp a trecut de la un event la altul, când a închis, etc. Tot ce ţine de acea convorbire.

Problema e că acest cod îmi zice doar cine a răspuns ultimul la telefon, chiar dacă convorbirea a trecut prin mâinile mai multor operatori, şi acum problema e că operatorii fiind compensaţi prin câte convorbiri rezolvă, foarte multe se pot pierde şi rapoartele pot fi înşelătoare…

Aşa că trebuie nu doar să traduc clasa iniţială, ci şi s-o modific ca să extrag din fiecare event ce se întâmplă.

In primu’ rand, mie codu’ ala imi pare decompilat. Which smells fishyyyyyy.
Nici nu e cod C# compilabil. Sau poate nu l-ai postat complet.

Poate sa fie si anul 4000. Ce e rau in a avea array-uri fixe? Poate ma iluminezi si pe mine.

3 Likes

Că nu mai eşti limitat de memorie, cum erai secolul trecut? :slight_smile: De ce ai limita arbitrar informaţia pe care ai putea s-o stochezi? Nu mai zic de posibilitatea a de comite overflow

1 Like

Pentru ca de pilda, in general fiecare om are maxim 10 degete, deci maxim 10 amprente. In plus, ideea de lista fara sa fie fixa e o abstractie, nu exista in low level. In functie de implementare, uneori e un array care se tot copiaza din stanga in dreapta ca sa aiba loc pentru noul element care il adaugi, chestie ineficienta. Nu sunt sigur, dar ma intreb daca uneori compilatorul nu e atat de destept incat daca ai scris cod f naspa, se prinde si foloseste un array fix in loc de o lista adevarata.

2 Likes

Da, este cod decomplilat, e in atașament la postul inițial clasa completă.

O facem așa pentru că nimeni nu mai are codul sursă, e mai vechi, și pe cine l-ar făcut pur și simplu nu-i mai interesează.

Trebuia să specific de la început poate.

Toată lumea are maximum 10 degete, cu excepţia celor… care au mai multe :slight_smile:

Ideea e că in destul de puţine cazuri array-ul este ceea ce ai tu nevoie. În cazul de faţă este mai eficient un map (denumit înşelător în PHP ca array).

Depinde şi cum trebuie să parcurgi acea colecţie de date. Dacă vrei secvenţial, foloseşti linked-list. Dacă ai nevoie de lookup-uri rapide, hash map. Dacă ai nevoie de ordonare şi lookup (relativ) rapid, foloseşti tree şamd. Array-ul mi se pare cea mai primitivă formă de stocare a datelor, pentru că e dificil de manipulat - insert, append, delete, toate sunt expensive. În afară de string-uri şi buffere pentru I/O nu prea văd unde s-ar preta array-uri în forma lor brută.

1 Like

this ca in multe limbaje e instanta curenta

CDRSummary.ClientEntry se refera cred la o clasa sau struct declarata in interiorul altei clase, cauta inner class pe google. In rest, cred ca tine de logica, dar fiind cod decompilat, arata ca dracu

Nope. O practica buna e ca daca chiar stii ca lista aia nu poate avea mai mult de 10 elemente, chiar e recomandat sa folosesti un array. Sau o lista readonly macar. In a fara de efficienta, Intr o logica complexa te poate ajuta sa dai de buguri rapid. Sau de scenarii la care nu te ai gandit.

1 Like

Hmm, ai avut multe cazuri reale în care să fi ştiut dinainte câte obiecte identice o să ai? Eu în cazurile astea mai degrabă folosesc un struct (folosesc terminologia C/C++). De exemplu în loc să am array[10] pentru degete, prefer o structură de genul

struct Mână {
  Deget mare;
  Deget aratator;
  Deget mijlociu;
  Deget inelar;
  Deget mic;
}

struct Mâini {
  Mână stânga;
  Mână dreaptă;
}

PS Cred ca ar trebui rupt topicul, pare catchy devierea, m-ar interesa şi părerea altora referitoare la subiectul ăsta.

degetele de la mana era un exemplu.
daca stii ca nu poti sa ai mai mult de x, nu folosesti o lista. sau macar folosesti dar gardezi cumva folosirea.
daca eficienta conteaza, prealocarea e cheie List in C# are o prealocare de doar 4 elemente, ce depaseste aloca array si copiaza

1 Like

Există totuşi şi aici nişte limite. Dacă ştii că array-ul poate avea 1 maximum un milion de elemente, nu te apuci să aloci un array de un milion de elemente :slight_smile:

Sau mă rog, ai putea face şi asta, depinde de limbaj şi de sistemul de operare. Nu ştiu cum e în alte părţi, dar în C/C++/Linux nu se alocă memorie fizică până nu se întâmplă să accesezi acel element (aşa numitul page fault). Dar chiar şi aşa, chiar şi memoria virtuală este o resursă limitată (deşi pe 64 de biţi cred că putem să spunem că e cvasi-nelimitată).

Depinde şi cum anume creezi acel array. Una e să creezi un milion de slot-uri (în C++ pur şi simplu poate fi un array de pointeri, pe 64 de biţi fiecare pointer ocupând 8 bytes) în care vor sta viitoarele instanţe ale obiectelor şi să le creezi/distrugi la nevoie şi cu totul altceva este să le pre-instanţiezi când instanţiezi array-ul (costă timp şi memorie virtuală şi, foarte posibil, şi memorie fizică).

Sunt nişte nuanţe la care ne gândim foarte rar în 2018 :slight_smile:

1 Like

Mă distrează filozofiile astea :))

Orice lucru e bun în contextul său. Câteodată dacă chiar vrei să fi sigur că eviţi necunoscutele, e perfect normal să pui un array limitat, dacă ştii sigur, şi poate chiar ai nevoie să fii sigur. Ce să zic dacă e vorba de ceva soft critic unde nu vrei să rişti nimic.

Revenind la subiect, continui cu conversia clasei, noroc că mai am un pic experienţă din Java şi fac legătura, codul e relativ straight-forward.

Mergând înainte, am mai întâmpinat nişte lucruri interesante de care sunt 99% sigur din ce am documentat.

Văd foarte des ceva de genul (le numesc eu stringVariable ca să înţelegeţi că e variabilă de tip string)

stringVariable.compareTo("ceva text") != 0

Asta bănuiesc că e echivalent cu strcmp care la fel, returnează zero dacă stringurile sunt egale, şi -1 sau 1 în funcţie de care e mai “mare”.

Apoi, am mai găsit:
stringVariable.indexOf("ceva text") < 0

Asta bănuiesc că ar fi echivalentul lui strpos din php, -1 dacă nu găseşte stringul, şi 0 sau mai mare care e de fapt indexul primului occurence. Nimic special.

În rest a mers bine traducerea, mulţumesc de ajutor.

1 Like

Ce e rau in a prealoca 1 mil de elemente cand e nevoie? In functie de cum se lucreaza cu array-ul ala, poate fi mai eficient decat sa folosesti o “lista”.
Dar nu despre asta vorbeam, cel putin nu despre asta vroiam eu sa vb in exemplul respectiv.

Alocarea din codul tau si page faulting sunt lucruri diferite si se intampla in layere diferite. Si nu vad legatura cu discutia de mai sus.

Eu ce vroiam mai sus sa zic e ca, fix pentru acel exemplu, daca din pct de vedere al business logic, array-ul ala nu poate avea niciodata mai mult de 10 elemente, folosirea unui array de 10 elemente e foarte OK, si chiar e recomandat. Mie defensive coding mi se pare foarte important.
O alternativa poate fi o clasa care encapsuleaza array-ul ala si dimensiunea de 10 elemente, depinde de cum se foloseste in toata aplicatia onceptul de acel array.

Conteaza daca sunt multe sau putine?

Ai dreptate, are sens ce zici, si folosirea unui struct face mult sens uneori.
Dar depinde de business logic.
Folosirea unui struct cred ca atunci cand ai nevoie sa stii fiecare element in parte. Dar uneori poate doar pur si simplu vrei sa pui in lista elementele, nu conteaza ordinea.