Documente Academic
Documente Profesional
Documente Cultură
Supraîncărcarea operatorilor
La fel ca in C++ operatorii pot fi supraîncărcați însă pe lângă asemănări sunt și unele
diferențe.
Sintaxa:
public static tip_rez operator op(tip parametru)
{ …}
public static tip_rez operator op(tip1 parametru1, tip2
parametru2)
{ …}
tip_rez reprezintă tipul valorii întoarse de operația op. Valoarea intoarsă poate fi
de orice tip, însa adeseori este de acelasi tip cu clasa pentru care are loc
supraincarcarea operatorului;
în cazul operatorului unar, parametru trebuie sa fie de același tip cu clasa pentru
care se redefinește operatorul. În cazul operatorului binar, cel putin unul din
operanzi (parametru1sau parametru2) trebuie sa fie de acelasi tip cu clasa
pentru care se redefineste operatorul.
parametrii operatorilor nu pot utiliza modificatorii ref și out.
Exemplu:
using System;
class Complex{
double re, im;
//constructori
public Complex(double re=0, double im=0)
{
this.re=re;
this.im=im;
}
public Complex(Complex z)
{
re=z.re;
im=z.im;
}
Transmiterea parametrilor
Pentru transmiterea parametrilor către metode avem la dispoziție: transferul prin valoare și
transferul prin referinta. În mod implicit, tipurile valorice sunt transferate metodelor prin
valoare, în timp ce obiectele sunt transferate prin referință.
-transferul prin valoare: Metoda copiază valoarea parametrului efectiv în parametrul
formal al subrutinei. Modificarile aduse parametrului subrutinei nu vor modifica valoarea
parametrului efectiv.
-transferul prin referinta: Se transmite parametrului formal o referință a parametrului
efectiv și nu valoarea acestuia. În interiorul subrutinei, referința este utilizată pentru accesul
la parametrul efectiv. Modificarile parametrului formal vor afecta și parametrul efectiv.
În mod implicit tipurile valorice sunt transferate catre metode prin valoare. Acest
comportament poate fi modificat cu ajutorul cuvintelor cheie ref si out.
Modificatorul ref:
se utilizeaza atunci când se dorește ca o anumită metodă să modifice parametrii
efectivi, forțează transferul prin referință în detrimentul transferului prin valoare;
apare atât în declarație cât și în apelul metodei. Parametrul transferat cu ref trebuie
sa aiba o valoare atribuita inainte de apel.
Modificatorul out:
se utilizează atunci când se dorește întoarcerea de către metodă a mai multor valori
mediului apelant. O instructiune return întoarece o singura valoare. Dacă se dorește
întoarcerea spre exemplu a doua valori atunci problema se rezolva cu ajutorul
modificatorului out.
apare atât în declarație cât și în apelul metodei. Nu este necesar ca variabila utilizată
ca parametru out să fie inițializată înainte de apelul metodei.
Exemplu:
class OClasa
{
protected internal int val;
public OClasa(int val)
{
this.val=val;
}
public int Val
{
get { return val; }
set { val = value; }
}
}
class Program
{
public static void Schimba(int i)
{
i=100;
}
public static void Schimba(ref int i)
{
i = 100;
}
public static void Schimba(OClasa i)
{
i.val = 100;//recunoscut deoarece val este "protected internal"
}
public static void Schimba(int[] i)
{
i[0]=100;
}
public static void Schimba(List<OClasa> i)
{
i[0].Val=100;
}
public static void Calcul(int x,int y,out int S,out int P)
{
S = x + y;
P = x * y;
}
static void Main(string[] args)
{
int i=1,j=2,suma,produs;
OClasa o = new OClasa(1);
int[] t = {1};
List<OClasa> l = new List<OClasa>();
l.Add(new OClasa(1));
Schimba(i);
Schimba(ref j);
Schimba(o);
Schimba(t);
Schimba(l);
Calcul(i, j, out suma,out produs);
Console.WriteLine(i);
Console.WriteLine(j);
Console.WriteLine(o.Val);
Console.WriteLine(t[0]);
Console.WriteLine(l[0].Val);
Console.WriteLine("Suma: "+suma);
Console.WriteLine("Produs: "+produs);
}
}
În urma execuției obținem:
1
100
100
100
100
Suma: 101
Produs: 100
Press any key to continue . . .
Moștenirea
În C# moștenirea este asemănătoară celei din C++, dar există și unele deosebiri. În
C++ clasele și structurile sunt practic identice în timp ce în C # ele sunt destul de diferite.
În C# clasele pot implementa orice număr de interfețe, dar nu pot face moștenire multiplă
(pot moșteni de la o singură clasă de bază). Se poate deriva doar cu public. Mai mult
decât atât, în C# structurile nu acceptă moștenire, și nu acceptă constructori expliciți (unul
este prevăzut în mod implicit).
Important: este disponibil un nou specificator de acces protected internal (membrii
sunt vizibili atat în clasele care moștenesc clasa în care sunt definiți acești membri cât și în
cadrul grupului de fișiere care formează asamblajul).
În C#, într-o clasa derivată, se poate utiliza cuvântul rezervat base pentru a apela
membrii suprascriși ai clasei de bază.
În cazul ierarhiilor de clase pe mai multe cuvântul base referă întodeauna elementele din
clasa de bază cea mai apropiată.
O clasa care contine o metodă abstractă trebuie declarată ea insăși abstractă, precedând
declaratia class cu specificatorul abstract. Deoarece clasele abstracte nu definesc
Limbajul C# definește o clasă specială, numită object, care este clasa de bază implicită
pentru toate celelalte clase și pentru toate celelalte tipuri, inclusiv tipurile valorice. Din
punct de vedere tehnic, numele C# object este sinonim pentru System.Object, din
arhitectura .NET.
Clasa object defineste mai multe metode, disponibile pentru orice obiect, cum ar fi:
bool Equals (object) Determina daca obiectul apelant este acelasi cu cel referit
bool Determina daca parametrii refera acelasi obiect.
Equals(object,object)
string ToString() Intoarce un string care descrie obiectul
Finalize() Executa actiunile de distrugere a obiectului, anterioare
colectarii spatiului ocupat de acesta. Finalize() se
acceseaza prin intermediul destructorilor.
Exemplu:
using System;
După execuție:
Clasa derivata A
Clasa derivata B
a=2,3
in clasa de baza a=0
Press any key to continue . . .
O prima posibilitate de a determina tipul unui obiect este aceea de a utiliza metoda
GetType(), pe care toate clasele o moștenesc de la clasa object, în combinație cu
operatorul typeof().
Exemplu:
if (a.GetType() == typeof(clasaDerivataA))
{
Console.WriteLine("Abiectul \"a\" este instanta a clasei clasaDerivataA");
}
else
{
Console.WriteLine("Abiectul \"a\" nu este instanta a clasei clasaDerivataA");
}
O altă posibilitate este de a utiliza operatorul is. Acest operator ne permite să determinăm
dacă un obiect este sau poate fi convertit într-un tip dat.
Sintaxă:
<operand> is <type>
Dacă <type> este o clasă atunci rezultatul este true dacă <operand> este de
tipul acelei clase sau de tipul unei clase derivate din clasa <type> sau poate fi
împachetat in acel tip;
Dacă <type> este o interfață atunci rezultatul este true dacă <operand> este
de acel tip sau dacă este de un tip care implementează acea interfață;
Dacă <type> este un tip valoric atunci rezultatul este true daca <operand>
este de acel tip sau este de un tip care poate fi despachetat în acel tip.
Exemplu:
using System;
class Animal{
public virtual void scrie()
{
Console.WriteLine("Sunt din clasa Animal");
}
public static int da_numar_picioare(Animal animal){
if(animal is Pisica)return 4;
if(animal.GetType()==typeof(Pasare))return 2;
return -1;
}
}
class Pisica: Animal{
String nume;
public Pisica(String nume)
{
this.nume=nume;
}
public override void scrie(){
Console.WriteLine("Sunt din clasa Pisica si ma cheama {0}.",nume);
}
}
class Pasare: Animal{
String nume;
public Pasare(String nume)
{
this.nume=nume;
}
public override void scrie(){
Console.WriteLine("Sunt din clasa Pasare si ma cheama {0}.",nume);
}
}