Kako postaviti pametne telefone i računala. Informativni portal
  • Dom
  • OS
  • Operateri su oštri. Uvjetni izrazi

Operateri su oštri. Uvjetni izrazi

Zadnje ažuriranje: 19.06.2017

C # koristi većinu operacija koje se koriste u drugim programskim jezicima. Operacije predstavljaju specifične akcije nad operandima koji su sudionici operacije. Operand može biti varijabla ili neka vrijednost (na primjer, broj). Operacije mogu biti unarne (izvode se na jednom operandu), binarne - na dva operanda i ternarne - na tri operanda. Razmotrimo sve vrste operacija.

Binarne aritmetičke operacije:

    Operacija zbrajanja dva broja:

    Int x = 10; int z = x + 12; // 22

    Operacija oduzimanja dva broja:

    Int x = 10; int z = x - 6; // 4

    Operacija množenja dva broja:

    Int x = 10; int z = x * 5; // 50

    operacija dijeljenja dva broja:

    Int x = 10; int z = x / 5; // 2 dvostruko a = 10; dvostruko b = 3; dvostruko c = a / b; // 3.33333333

    Prilikom dijeljenja, imajte na umu da ako oba operanda predstavljaju cijele brojeve, tada će i rezultat biti zaokružen na cijeli broj:

    Dvostruki z = 10/4; // rezultat je 2

    Unatoč činjenici da se rezultat operacije na kraju stavlja u varijablu tipa dvostrukošto vam omogućuje uštedu frakcijski dio, ali sama operacija uključuje dva literala, koji se prema zadanim postavkama tretiraju kao int objekti, odnosno cijeli brojevi, a rezultat će biti isti kao cijeli broj.

    Da biste izašli iz ove situacije, potrebno je definirati literale ili varijable koje sudjeluju u operaciji, točno kao tipove double ili float:

    Dvostruki z = 10,0 / 4,0; // rezultat je 2,5

    Operacija dobiva ostatak cjelobrojna podjela dva broja:

    Dvostruki x = 10,0; dvostruki z = x% 4,0; // rezultat je 2

Tu je i broj unarne operacije, u kojem sudjeluje jedan operand:

    Operacija povećanja

    Povećanje može imati prefiks: ++ x - prvo se vrijednost varijable x povećava za 1, a zatim se vraća njena vrijednost kao rezultat operacije.

    A tu je i postfix inkrement: x ++ - prvo se kao rezultat operacije vraća vrijednost varijable x, a zatim joj se dodaje 1.

int x1 = 5; int z1 = ++ x1; // z1 = 6; x1 = 6 Console.WriteLine ($ "(x1) - (z1)"); int x2 = 5; int z2 = x2 ++; // z2 = 5; x2 = 6 Console.WriteLine ($ "(x2) - (z2)");

Operacija dekrementiranja ili dekrementiranja vrijednosti za jedan. Također postoji dekrement prefiksa (--x) i postfiks (x--).

Int x1 = 5; int z1 = --x1; // z1 = 4; x1 = 4 Console.WriteLine ($ "(x1) - (z1)"); int x2 = 5; int z2 = x2--; // z2 = 5; x2 = 4 Console.WriteLine ($ "(x2) - (z2)");

Kada izvodite nekoliko aritmetičkih operacija odjednom, razmotrite redoslijed kojim se one izvode. Prioritet operacija od najvišeg do najnižeg:

    Povećanje, smanjenje

    Množenje, dijeljenje, dobivanje ostatka

    Zbrajanje, oduzimanje

Zagrade se koriste za promjenu redoslijeda operacija.

Razmotrimo niz operacija:

Int a = 3; int b = 5; int c = 40; int d = c --- b * a; // a = 3 b = 5 c = 39 d = 25 Console.WriteLine ($ "a = (a) b = (b) c = (c) d = (d)");

Ovdje imamo posla s tri operacije: dekrementiranje, oduzimanje i množenje. Prvo se c smanjuje, zatim se b * a množi, a zatim oduzima. Naime, skup operacija izgledao je ovako:

Int d = (c -) - (b * a);

Ali uz pomoć zagrada mogli bismo promijeniti redoslijed operacija, na primjer, na sljedeći način:

Int a = 3; int b = 5; int c = 40; int d = (c - (- b)) * a; // a = 3 b = 4 c = 40 d = 108 Console.WriteLine ($ "a = (a) b = (b) c = (c) d = (d)");

Asocijativnost operatora

Kao što je gore navedeno, operacije množenja i dijeljenja imaju isti prioritet, ali kakav će onda biti rezultat u izrazu:

Int x = 10/5 * 2;

Trebamo li ovaj izraz tumačiti kao (10/5) * 2 ili kao 10 / (5 * 2)? Doista, ovisno o tumačenju, dobit ćemo različite rezultate.

Kada operacije imaju isti prioritet, redoslijed evaluacije određen je asocijativnošću operatora. Postoje dvije vrste operatora ovisno o asocijativnosti:

    Lijevi asocijativni operatori koji se izvršavaju s lijeva na desno

    Desno asocijativni operatori koji se izvršavaju s desna na lijevo

Sve aritmetički operatori(osim prefiksa inkrement i dekrement) su lijevo-asocijativni, odnosno izvode se s lijeva na desno. Stoga se izraz 10/5 * 2 mora tumačiti kao (10/5) * 2, odnosno rezultat će biti 4.

Operatori relacija i logičke operatore

U notaciji operator odnosa i logički operator termin odnos znači odnos koji može postojati između dva značenja i pojma logično- odnos između logičkih vrijednosti "točno" i "netočno". A budući da relacijski operatori daju istinite ili netočne rezultate, često se koriste u sprezi s logičkim operatorima. Iz tog razloga se smatraju zajedno.

Sljedeći su relacijski operatori:

Booleovi operatori uključuju sljedeće:

Rezultat izvršavanja operatora relacije ili logičkog operatora je booleova vrijednost tipa bool.

Općenito, objekti se mogu usporediti za jednakost ili nejednakost pomoću relacijskih operatora == i! =. Operatori za usporedbu, =, mogu se primijeniti samo na tipove podataka koji podržavaju odnos redoslijeda. Stoga se relacijski operatori mogu primijeniti na sve numeričke tipove podataka. Ali bool vrijednosti se mogu usporediti samo za jednakost ili nejednakost, budući da istinite i lažne vrijednosti nisu poredane. Na primjer, usporedba true> false u C # je besmislena.

Razmotrimo primjer programa koji pokazuje upotrebu relacijskih i logičkih operatora:

Korištenje sustava; koristeći System.Collections.Generic; korištenjem System.Linq; koristeći System.Text; imenski prostor ConsoleApplication1 (klasa Program (statički void Main (string args) (kratko d = 10, f = 12; bool var1 = true, var2 = false; if (df) Console.WriteLine ("d> f"); // Usporedi varijable var1 i var2 if (var1 & var2) Console.WriteLine ("Ovaj tekst neće biti prikazan"); if (! (var1 & var2)) Console.WriteLine ("! (var1 & var2) = true"); ako (var1 | var2) Console.WriteLine ("var1 | var2 = true"); if (var1 ^ var2) Console.WriteLine ("var1 ^ var2 = true"); Console.ReadLine ();)))

Booleovi operatori u C # izvode najčešće logičke operacije. Ipak, postoji niz operacija koje se izvode prema pravilima formalne logike. Ove logičke operacije mogu se izgraditi korištenjem booleovih operatora podržanih u C #. Stoga C# pruža takav skup logičkih operatora, koji je dovoljan za konstruiranje gotovo svake logičke operacije, uključujući implikacije. Implikacija je binarna operacija koja je netočna samo ako njezin lijevi operand ima pravo značenje a desna je lažna. (Operacija implikacije odražava sljedeće načelo: istina ne može značiti laž.)

Operacija implikacije može se izgraditi na temelju kombinacije logičkih operatora! i |:

Skraćeni logički operatori

C # također nudi posebne, skraćeno, varijante logičkih operatora AND i OR, dizajnirane za dobivanje učinkovitijeg koda. Objasnimo ovo na sljedeći primjeri logičke operacije. Ako je prvi operand logičke AND operacije lažan, tada će njegov rezultat biti lažan bez obzira na vrijednost drugog operanda. Ako prvi operand logičke operacije ILI ima istinitu vrijednost (true), tada će njegov rezultat imati istinitu vrijednost bez obzira na vrijednost drugog operanda. Zbog činjenice da vrijednost drugog operanda u ovim operacijama nije potrebno izračunati, štedi vrijeme i poboljšava učinkovitost koda.

Skraćena logička I operacija se izvodi pomoću operater &&, i skraćenu logičku operaciju ILI koristeći operator ||... Ovi skraćeni logički operatori odgovaraju uobičajenim logičkim operatorima & i |. Jedina razlika između skraćenog logičkog operatora i običnog je u tome što se njegov drugi operand procjenjuje samo prema potrebi.

U C # nema implicitnih logičkih konverzija, čak ni za cijele brojeve aritmetičke vrste... Stoga je notacija sasvim ispravna u jeziku C ++:

intk1 = 7;
ako (k1) Konzola. WriteLine(" u redu!");

nezakonito u C # programima. U fazi prijevoda pojavit će se pogreška jer izračunati uvjet ima tip int, i implicitna konverzija ove vrste u tip bool nedostaje.

U C # stroža pravila vrijede i za logičke operacije. Dakle, ulaz ako(k1 && (x> y)), ispravno u C ++, rezultira pogreškom u

C # programira jer je && definiran samo za operande tipa bool, i u ovom izrazu, jedan od operanada je tipa int. U jeziku C #, u ovim situacijama, trebali biste koristiti sljedeće unose:

ako(k1>0)
ako((k1>0) && (x> y))

Logičke operacije podijeljene su u dvije kategorije: neke se izvode na logičkim vrijednostima operanada, dok druge izvode logičke operacije nad bitovima operanada. Iz tog razloga, u C # postoje dva unarna negacija operatora — logička negacija, specificirana operatorom!, i bitna negacija, specificirana operatorom ~. Prvi je definiran preko operanda tipa bool, drugi - preko operanda cjelobrojnog tipa, počevši od tipa int i više (int, uint, dugo, ulong). Rezultat operacije u drugom slučaju je operand u kojem je svaki bit zamijenjen svojim komplementom. Navedimo primjer:

/// < Sažetak>
/// Booleovi izrazi
/// Sažetak>
javnostponištitiLogika() {
// operacije negacije ~,!
bool b1, b2;
b1= 2*2 == 4;
b2= b1;
// b2 = ~ b1;
jedinica j1= 7, j2;
j2= ~ j1;
// j2= !j1;
int j4= 7, j5;
j5= ~ j4;
Console.WriteLine ("uint j2= " + j2+ " int j5= " + j5);
} // Logika

U ovom su isječku izjave koje dovode do pogrešaka komentirane. U prvom slučaju pokušano je primijeniti operaciju negacije po bitu na izraz kao što je bool, u drugom je logička negacija primijenjena na cjelobrojne podatke. Oba su ilegalna u C #. Obratite pažnju na različita tumačenja bitne negacije za neoznačene i predpisane cjelobrojne tipove. Za varijable j5 i j2 bitni niz koji definira vrijednost je isti, ali se različito tumači. Odgovarajući zaključak je sljedeći:

uintj2 = 4294967288
intj5 = -8.

Binarne logičke operacije" && - kondicional I "i" || - uvjetni OR "definirani su samo nad podacima tipa bool. Operacije se nazivaju uvjetne ili kratke, jer izračun drugog operanda ovisi o već izračunatoj vrijednosti prvog operanda. Vrijednost uvjetnih logičkih operacija leži u njihovoj učinkovitosti u smislu vremena izvršenja. Često vam omogućuju izračunavanje boolean izraz to ima smisla, ali u kojem je drugi operand nedefiniran. Uzmimo za primjer klasični problem pretraživanja po uzorku u nizu, kada se traži element sa zadanom vrijednošću (uzorkom). Takav element u nizu može, ali i ne mora biti. Ovdje je tipično rješenje ovog problema u pojednostavljenom obliku, ali prenosi bit stvari:

// UvjetovanoI- &&
int [] ar= { 1, 2, 3 };
int pretraga= 7;
int i= 0;
dok ja< ar.duljina)&& (ar [i]!= traži)){
ja ++;
}
ako ja< ar.duljina)Console.WriteLine ("Uzorakpronađeno");
drugoConsole.WriteLine ("Uzoraknepronađeno");

Ako vrijednost varijable traži(uzorak) ne odgovara nijednoj od vrijednosti elemenata niza ar, zatim posljednja provjera stanja petlje dok izvršit će se ako vrijednost i, jednak ar. Duljina. U ovom slučaju, prvi operand će primiti vrijednost lažno, i iako drugi operand nije definiran, petlja će normalno završiti. Drugi operand je nedefiniran u zadnja provjera jer je indeks elementa u nizu izvan raspona (u C # indeksiranje elemenata počinje od nule).

Tri binarne bitne operacije- "& - I", "| - OR "," ^ - XOR "koriste se na dva načina. Definirani su kao gore navedeni cjelobrojni tipovi int, i preko booleovih tipova. U prvom se slučaju koriste kao bitne operacije, u drugom kao obične logičke operacije. Ponekad je potrebno da se oba operanda u svakom slučaju izračunaju, tada se te operacije ne mogu izbjeći. Evo primjera njihove prve upotrebe:

// Logičke operacije u bitovimaI, Ili, XOR(&,|,^)
int k2= 7, k3= 5, k4, k5, k6;
k4= k2& k3;
k5= k2 | k3;
k6= k2 ^k3;
Console.WriteLine ("k4= " + k4+ " k5= " + k5+ " k6= " + k6);

Izlazni rezultati:

k4 = 5 k5 = 7 k6 =2

Evo primjera pretraživanja uzorka pomoću logičkog I: i= 0;

traži= ar;
dok ja< ar.duljina)& (ar [i]!= traži)) i ++;
ako ja< ar.duljina)Console.WriteLine ("Uzorakpronađeno");
ostalo cConsole.WriteLine ("Uzoraknepronađeno");

Zajamčeno je da ovaj fragment ima uzorak pretraživanja u nizu, a fragment će se uspješno izvršiti. U istim slučajevima kada niz ne sadrži element traži, bit će izbačena iznimka. Smisleno značenje takvog postupka - pojava iznimke - može biti znak pogreške u podacima, što zahtijeva posebno postupanje sa situacijom.

POGLAVLJE 10. Izrazi i operatori

U ovom ćemo poglavlju pogledati temelje svakog programskog jezika — njegovu sposobnost izvršavanja zadataka i usporedbi pomoću operatora. Vidjet ćemo koji su operatori u C # i koji je njihov prioritet, a zatim ćemo zaroniti u pojedinačne kategorije izraza za izvođenje aritmetičkih operacija, dodjelu vrijednosti i usporedbu operanada.

Operateri

Operator je simbol koji označava operaciju koju treba izvesti na jednom ili više argumenata. Kada se naredba izvrši, dobiva se rezultat. Sintaksa za korištenje operatora malo se razlikuje od pozivanja metoda i trebali biste znati format izraza koji sadrže operatore u C # kao svoj stražnji dio ruke. Kao i kod većine drugih jezika, semantika operatora u C # slijedi pravila i oznake koje su nam poznate iz škole. Osnovni operateri u C # uključuje množenje (*), dijeljenje (/), zbrajanje i unarni plus (+), oduzimanje i unarni minus (-), modul (%) i dodjeljivanje (=).

Operatori se koriste za dobivanje nove vrijednosti iz vrijednosti na kojima se radi. Ove početne vrijednosti se nazivaju operandi. Rezultat operacije mora biti pohranjen u memoriji. Ponekad se pohranjuje u varijablu koja sadrži jedan od originalnih operanada. C # prevodilac generira poruku o pogrešci ako nova vrijednost nije definirana ili pohranjena kada se koristi operator. Kod u nastavku ne mijenja vrijednosti. Prevoditelj će izdati poruku o pogrešci jer se aritmetički izraz koji ne mijenja barem jednu vrijednost obično smatra greškom.

klasa NoResultApp

{

javni statički void Main ()

{

int i; int j;

i + j; // Pogreška jer rezultat nije dodijeljen ničemu. )>

Većina operatora radi samo s brojčanim tipovima podataka kao što su Byte, Short, Long, Integer, Single, Double i Decimal. Iznimka su operatori usporedbe (== i! =). Također, u C # možete koristiti + i - operatore za klasu Niz pa čak i koristiti operatore inkrementa (++) i (-) za neobične jezične konstrukcije kao što su delegati. O potonjem ću govoriti u 14. poglavlju.

Operaterski staž

Kada se u jednom izrazu nalazi više naredbi, prevodilac mora odrediti redoslijed njihovog izvršavanja. U ovom slučaju, prevodilac se vodi pravilima tzv staž operatera. Razumijevanje prednosti operatora je neophodno za ispravan pravopis izrazi - ponekad rezultat možda neće biti očekivan.

Razmislite o izrazu 42 + 6 * 10. Ako zbrojite 42 i 6, a zatim zbroj pomnožite sa 10, dobit ćete 480. Ako pomnožite 6 sa 10 i rezultatu dodate 42, dobit ćete 102. Prilikom sastavljanja koda, posebna komponenta prevoditelja je - leksički analizator - odgovoran je za redoslijed čitanja ovog koda. Leksički analizator je taj koji određuje relativni prioritet heterogenih operatora u jednom izrazu. Da bi to učinio, koristi neku vrijednost - prioritet - svakog podržanog operatora. Najprije su dopušteni operateri višeg prioriteta. U našem primjeru, * operator ima prednost nad + operatorom, budući da * upija(sada ću objasniti ovaj pojam) moji operandi prije + to radi. Objašnjenje leži u općim pravilima aritmetike: množenju i dijeljenju. stalno imaju prednost nad zbrajanjem i oduzimanjem. Vratimo se na primjer: kažu da je broj 6 progutano operator * u oba 42 + 6 * 10 i 42 * 6 + 10, tako da su ovi izrazi ekvivalentni 42 + (6 * 10) i (42 * 6) + 10.

Kako je staž definiran u C #

Pogledajmo sada kako je prioritet operatora definiran u C #. Operateri su navedeni u nastavku u silaznom redoslijedu prioriteta (Tablica 10-1). Kasnije ću detaljnije o različitim kategorijama operatora podržanih u C #.

Tab. 10-1. Prioritet operatora u C #.

Kategorija operatera Operateri
Jednostavan (x), xy, f (x), a [x], x ++, x -, novo, typeof, sizeof, označeno, neoznačeno
Unarno +, -,!, ++ x, - x, (T) x
Multiplikativno *,/, %
Aditiv +, -
Shift «, »
Stav <, >, <=, >=, je
Jednakost ==
Logično I (I) &
Logičko isključivo OR (XOR) ^
Logično ILI (ILI) 1
Uvjetno I &&
Uvjetni IL I (ILI) II
Stanje 9-
Zadatak = *= /= % = , + = , -= « = , » = , &=, ^ = , =

Lijeva i desna asocijativnost

Asocijativnost određuje koji dio izraza treba prvo procijeniti. Na primjer, rezultat gornjeg izraza može biti 21 ili 33, ovisno o tome koja će se asocijativnost koristiti za operator "-": lijevo ili desno.

Operator - ima lijevu asocijativnost, odnosno prvo se izračuna 42-15, a zatim se od rezultata oduzima 6. Da ima desnu asocijativnost, prvo bi se izračunala desna strana izraza (15-6), a zatim rezultat bi se oduzelo od 42.

Svi binarni operatori (operatori s dva operanda), osim operatora dodjele, - lijevo-asocijativno, odnosno obrađuju izraze s lijeva na desno. Na ovaj način, a + b+ sa - isto kao (a + b) + c, gdje se prvo izračunava a + b, a zatim se zbroj zbroji S. Operatori dodjele i uvjetni iskazi - desno asocijativno, odnosno obrađuju izraze s desna na lijevo. Drugim riječima, a = b = c ekvivalentno a = (b= S). Mnogi ljudi naiđu na ovo kada žele staviti nekoliko naredbi o dodjeli u jedan red, pa pogledajmo ovaj kod:

korištenje sustava;

klasa RightAssocApp (

javni statički void Main () (

int a = 1; int b = 2; int c = 3;

Console.WriteLine ("a = (0) b = (1) c = (2>", a, b, c); a = b = c;

Console.WriteLine ("Nakon" a = b = c -: a = (0) b = (1) c = (2) ", a, b, c);>>

Rezultat izvođenja ovog primjera je sljedeći:

a = 1 b = 2 c = 3

Nakon "a = b = c": a = 3 b = 3 o = 3

Vrednovanje izraza s desna na lijevo može isprva biti zbunjujuće, ali pristupimo tome na sljedeći način: ako je operator dodjeljivanja lijevo asocijativan, prevodilac bi prvo morao procijeniti a = b, zatim a bio bi jednak 2 i tada b= s i kao rezultat b bilo bi 3. Krajnji rezultat bi bio a = 2 b = 3 c = 3. Očito, to nije ono što očekujemo kada pišemo a= b= S, i zato su asocijacija i uvjetni operatori desno-asocijativni.

Praktična upotreba

Ništa nije više problematično od pronalaženja greške samo zato što programer nije poznavao pravila prvenstva i asocijativnosti. Naišao sam na poruke na mail konferencijama u kojima su očito razumni ljudi predložili svojevrsni mehanizam samodokumentiranja - korištenje razmaka za označavanje operatera da, po njihovom mišljenju, imati staž. Na primjer, budući da znamo da operator množenja ima prednost nad operatorom zbrajanja, trebali bismo napisati nešto poput ovoga, u kojem razmaci označavaju podrazumijevano staž:

a = b * c + d;

Ovaj pristup je u osnovi pogrešan: prevodilac ne može ispravno raščlaniti kod ako specifična sintaksa nije definirana. Prevoditelj analizira kod prema pravilima definiranim od strane programera prevoditelja. S druge strane, postoje okrugle zagrade koristi se za eksplicitno označavanje prvenstva i asocijativnosti. Na primjer, izraz a= b * c + d može se prepisati kao a = (b * c) + d ili kako a= b * (c + d) a prevodilac će prvo procijeniti izraz u zagradama. Ako postoji više parova zagrada, prevodilac će prvo procijeniti izraze u zagradama, a zatim cijeli izraz, na temelju opisanih pravila prioriteta i asocijativnosti.

Moje je čvrsto uvjerenje da se zagrade uvijek trebaju koristiti kada u izrazu postoji više operatora. Preporučam da to učinite čak i ako razumijete redoslijed izračunavanja, jer ljudi koji će održavati vaš kod možda neće biti toliko pismeni.

C # operatori

Najispravnije je operatere smatrati prema stažu. U nastavku ću opisati najčešće operatore.

Jednostavni operateri

  • (x) Ovo je varijacija operatora zagrade za kontrolu redoslijeda evaluacije kao u matematičke operacije a pri pozivanju metoda.
  • xy Operator točka koristi se za označavanje člana klase ili strukture. Ovdje x predstavlja entitet koji sadrži člana na.
  • f (x) Ova vrsta operatora zagrade koristi se za popis argumenata metode.
  • Oh] Uglate zagrade koriste se za indeksiranje niza. Ove zagrade se također koriste zajedno s indekserima kada se objekti mogu tretirati kao niz. Za indeksere, vidi poglavlje 7.
  • h ++ O operatoru inkrementa ćemo govoriti zasebno u odjeljku "Operatori inkrementa i dekrementa".
  • x- O operatoru dekrementa bit će riječi kasnije.
  • new Ovaj operator se koristi za instanciranje objekata na temelju definicije klase.

vrsta

Odraz(refleksija) je sposobnost dobivanja informacija o tipu tijekom izvođenja. Ove informacije uključuju nazive tipova, klasa i članova strukture. V. NET Framework ova je funkcionalnost povezana s klasom Sustav. Tip. Ova klasa je korijen svih operatora refleksije i može se dobiti pomoću operatora vrsta. Nećemo sada ulaziti u detalje refleksije (to ćemo učiniti u 16. poglavlju), ali evo jednostavnog primjera koji ilustrira koliko je jednostavno koristiti operator vrsta"da biste dobili gotovo sve informacije o vrsti ili objektu tijekom izvođenja programa:

korištenje sustava;

korištenjem System.Reflection;

javna klasa jabuka (

public int nSeeds;

javna praznina Ripen ()

{

> >

javna klasa TypeOfApp (

javni statički void Main () (

Vrsta t = typeof (Apple);

string Ime klase = t.ToStringO;

Console.IgShip ("\ nInformacija 0 klasa (O)", className);

Console.WriteLine ("\ nMeroflH (0)", className); Konzola. WriteLine ("-------"); Metodlnfo metode = t.GetMethodsO;

foreach (metoda MethodInfo u metodama)

Console.WriteLine (metod.ToSt ring ());

}

Console.WriteLine ("\ nBce members (O)", className); Konzola. Writel_ine ("--------"); Članovi svi članovi = t.GetMembersO; foreach (član u svim članovima)

{

Konzola. WriteLine (član.ToStringO);

} > }

Ovaj program sadrži klasu Jabuka koja ima samo dva člana: polje nSjemenke i metoda Sazrijevati. Prvo, pomoću operatora vrsta i naziv klase dobivam objekt Sustav. Tip, koji se zatim pohranjuje u varijablu t. S u ovom trenutku mogu koristiti objekt Sustav. Tip da dobijete sve metode i članove klase Jabuka. To se radi pomoću metoda GetMethods i GetMembers odnosno. Rezultati ovih metoda su prikazani na standardni uređaj izlaz na sljedeći način:

Informacije o Razred jabuka Metode jabuke

Int32 GetHashCodeQ

System.String ToStringQ

Void RipenO

System.Type GetTypeO

Svi Apple članovi

Int32 nSjeme

Int32 GetHashCodeO

Boolean je jednak (System.Object)

System.String ToStringO

Void RipenO

System.Type GetTypeO

Prije nego što krenem dalje, želim istaknuti dvije točke. Prvo, primijetite da se također inferiraju naslijeđeni članovi klase. Budući da klasa nije eksplicitno izvedena iz druge klase, znamo da svi članovi nisu definirani u klasi Jabuka naslijediti od implicitne osnovne klase Sustav.Objekat. Drugo, objekt Sustav.Tip može se dobiti metodom GetType. Ovo je naslijeđeno od Sustav.Objekat metoda vam omogućuje rad s objektima, a ne s klasama. Bilo koji od dva isječka u nastavku može se koristiti za dobivanje objekta Sustav. Tip.

II Dobivanje objekta System.Type na temelju definicije klase. Vrsta t1 = typeof (Apple);

// Dobivamo objekt System.Type iz objekta. jabuka jabuka= novi AppleQ; Upišite t2 = apple.GetTypeO;

veličina

Operater veličina koristi se za dobivanje veličine navedene vrste u bajtovima. Pritom se sjetite isključivo dvoje važni čimbenici... Prvo, veličina može se primijeniti samo na tipove dimenzija. Stoga, iako se može koristiti za članove klase, ne može se koristiti za klase kao takve. Drugo, veličina može se koristiti samo u metodama ili blokovima koda označenim kao nesigurno. S S ovakvom vrstom koda ćemo se upoznati u poglavlju 17. Evo primjera korištenja operatora veličina u metodi klase označene kao nesigurno:

korištenje sustava;

klasa BasicTypes (

// Napomena: kod koji koristi operator sizeof // mora biti označen kao nesiguran, statički nesiguran public void ShowSizesQ (

Console.WriteLine ("\ nPa3Mephi glavne vrste"); Console.WriteLine ("Pa3Mep short = (0)", sizeof (short)); Console.WriteLine ("Pa3Mep int = (0)", sizeof (int)); Console.Writel_ine ("Pa3Mep long = (0)", sizeof (long)); Console.WriteLine ("Pa3Mep bool = (0)", sizeof (bool)); ))

klasa UnsafeUpp

{

nesigurna javna statička praznina MainQ

{

BasicTypes.ShowSizes ();

} }

Evo izlaza iz ove aplikacije:

Veličine osnovnih tipova Veličina kratka = 2 Veličina int = 4 Veličina duga = 8 Veličina bool = 1

Operater veličina može se koristiti za definiranje dimenzija ne samo za jednostavne ugrađene tipove, već i za prilagođene tipove dimenzija kao što su strukture. Međutim, rezultati veličina možda nije očito:

// Korištenje operatora sizeof. korištenje sustava;

struct StructWithNoMembers

struct StructWithMembers

{

kratki s;

int i;

dugo 1;

bool b; )

struct CompositeStruct

{

StructWithNoMembers a; StructWithMembers b;

StructWithNoMembers c; )

klasa UnSafe2App (

nesiguran javni statički void Main () (Console.WriteLine ("\ nPa3Mep StructWithNoMembers struktura = (0)",

sizeof (StructWithNoMembers)); Console.WriteLine ("\ nPa3Mep StructWithMembers struktura = (0)",

sizeof (StructWithMembers)); Console.WriteLine ("\ nPa3Mep CompositeStruct struktura = (0)",

sizeof (CompositeStruct)); ))

Iako se može pretpostaviti da će ova aplikacija ispisati 0 za strukturu bez članova (StructWithNoMembers), 15 za strukturu s četiri člana baznih tipova (StructWithMembers) i 15 za strukturu koja objedinjuje dvije prethodne (CompositeStruct), u stvarnosti će rezultat biti ovakav:

Struktura veličine StructWithNoMembers = 1 Struktura veličine StructWithMembers = 16

Veličina kompozitne strukture = 24

Objašnjenje za to je način zadržavanja konstrukcije strukturirati prevodilac u izlaznoj datoteci gdje prevodilac primjenjuje opravdanje i padding. Na primjer, ako je struktura veličine 3 bajta i poravnata na granicama od 4 bajta, prevodilac će strukturi automatski dodati 1 bajt, a operator veličinaće označiti da je veličina strukture 4 bajta. Ne zaboravite to imati na umu kada dimenzionirate strukture u C #.

provjereno i neprovjereno

Ova dva operatora kontroliraju provjeru preljeva prilikom izvođenja matematičkih operacija.

Matematički operatori

C #, kao i većina drugih jezika, podržava osnovne matematičke operatore: množenje (*), dijeljenje (/), zbrajanje (+), oduzimanje (-) i modul (%). Svrha prva četiri operatora je jasna iz njihovih imena; operator modula tvori ostatak cjelobrojnog dijeljenja. Evo malog koda koji ilustrira upotrebu matematičkih operatora:

korištenje sustava;

razred MathOpsApp

{

javna statička praznina MainQ

{

// Klasa System.Random dio je // biblioteke klasa .NET Framework. U svom zadanom konstruktoru, // metoda Next koristi trenutni datum/vrijeme kao // početna vrijednost... Random rand = novi RandomO; int a, b, c;

a = rand.Sljedeće () % jedna stotina; // Granična vrijednost 99. b = rand.NextO % 100; // Granična vrijednost 99.

Console.WriteLine ("a = (0) b = (1)", a, b);

c = a * b;

Console.WriteLineC "a * b = (0)", c);

// Imajte na umu da se ovdje koriste cijeli brojevi. // Stoga, ako je a manji od b, rezultat će uvijek // biti 0. Da biste dobili točniji rezultat // trebate upotrijebiti varijable poput dvostruko ili plutajuće, c = a / b; Console.WriteLineC "a / b = (0)", c);

Console.WriteLineC "a + b = (0)", c);

Console.WriteLineC "a - b = (0)", c);

Console.WriteLineC "a X b = (0)", c); >>

Unarni operatori

Postoje dva unarna operatora: plus i minus. Unarni minus operator govori prevoditelju da je broj negativan. Dakle, u sljedećem kodu a bit će jednako -42:

korištenje sustava; korištenje sustava;

klasa UnarylApp (

javni statički void Main ()

{

int a = 0;

a = -42;

Console.WriteLine ("(0)", a); ))

Međutim, nejasnoća se pojavljuje u ovom kodu: korištenje sustava;

razred Unary2App<

javni statički void Main () (

int a; int b = 2; int c = 42;

a = b * -c;

Console.WriteLine ("(0)", a); >>

Izraz a= b * -c nije sasvim jasno. Opet, korištenje zagrada će pojasniti ovaj izraz:

// Kada se koriste zagrade, očito je da // množimo b negativnim brojem c. a = b * (-c);

Ako se vrati unarni minus negativno značenje operand, moglo bi se pomisliti da bi se unarni plus vratio pozitivno. Međutim, unarni plus samo vraća operand u njegovom izvornom obliku i ne radi ništa drugo, odnosno ne utječe na operand. Na primjer, pokretanje ovog koda će dati vrijednost -84:

korištenje sustava;

klasa UnarySapp (

javna statička praznina MainQ (

a = b * (+ c);

Console.WriteLine ("(0)", a); ))

Da biste dobili pozitivnu vrijednost, koristite funkciju Math.Abs. Ovaj kod će ispisati vrijednost 84:

korištenje sustava;

razred Unary4App

{

javni statički void Main ()

int a; int b = 2; int c = -42;

a = b * Math.Abs ​​(c); Console.Writel_ine ("(0)", a); ))

Posljednji unarni operator koji sam spomenuo je T (x). Ovo je varijacija operatora zagrade koji vam omogućuje prebacivanje s jedne vrste na drugu. Budući da se može preopteretiti stvaranjem prilagođene transformacije, raspravljat ćemo o tome u 13. poglavlju.

Složeni operatori dodjele

Složeni operator dodjele - to je kombinacija binarnog operatora i operatora dodjele (=). Sintaksa za ove operatore je sljedeća:

pripjev = y

gdje op - ovo je operater. Imajte na umu da kada to radite, lijeva vrijednost (lvrijednost) nije zamijenjeno pravom (rvalue), složena izjava ima isti učinak kao:

x = x op na

i lvrijednost koristi se kao osnova za rezultat operacije.

Primijetite da sam rekao "ima isti učinak". Prevoditelj ne prevodi izraz kao što je x + = 5 inča x= x + 5, on djeluje logično. S posebna pažnja trebate se osvrnuti na slučajeve kada lvrijednost je metoda. Razmotrite kod:

korištenje sustava;

klasa CompoundAssignmentlApp (

zaštićeni lnt elementi;

public int GetArrayElementO

{

povratni elementi;

}

CompoundAssignment1App () (

elementi = novi int;

elemenata = 42;

}

javni statički void Main () (

Aplikacija CompoundAssignmentlApp = nova CompoundAsslgnment1App ();

Console.WrlteLine ("(0>", app.GetArrayElement ());

app.GetArrayElement () = app.GetArrayElement () + 5; Console.WriteLine ("(0)", app.GetArrayElement ()); ). )

Obratite pažnju na označenu liniju - poziv metode Compound-AssignmentlApp.GetArrayElement a zatim mijenjam prvi element - ovdje sam koristio sintaksu:

x = x op na

Ovako će se generirati MSIL kod: // Neučinkovita tehnika: x = x op y.

Upravljana metoda public hldebyslg static void Main () 11

Entrypolnt

// Veličina koda 79 (Ox4f) .maxstack 4

Lokalno stanovništvo (klasa CompoundAssignmentlApp V_0)

IL_0000: newobj instanca void CompoundAssignmentlApp ::. Ctor () IL_0005: stloc.O IL_0006: Idstr "(OG IL_OOOb: ldloc.0 ILJJOOc: poziv instance int32

CompoundAssignmentlApp :: GetArrayElementO

IL_0011: ldc.14.0

IL_0012: Idelema ["mscorlib"] System.Int32

IL_0017: okvir [1 mscorlib "] System.Int32

IL_001c: call void ["mscorlib 1] System.Console :: WriteLine (klasa System.String, klasa System.Object)

IL_0021: ldloc.0

IL_0022: poziv instance int32 CompoundAssignmentlApp :: GetArrayElementO

IL_0027: Idc.i4.0

IL_0028: ldloc.0

IL_0029: poziv instance int32 CompoundAssignmentlApp:: GetArrayElementO

IL_002e: Idc.i4.0

IL_002f: ldelem.14

IL_0030: ldc.14.5

IL_0031: dodaj

IL_0032: stelem.14

IL_0033: Idstr "(0)"

IL_0038: ldloc.0

IL_0039: poziv

instanca int32 CompoundAssignmentlApp :: GetArrayElement () IL_003e: ldc.14.0

IL_003f: Idelema ["mscorlib"] Systera.Int32 IL_0044: okvir ["msoorlib"] System.Int32 IL_0049: call void ["mscorlib"] System.Console :: WriteLine

(klasa System.String, klasa System.Object) IL_004e: ret

) // kraj metode "CompoundAssignmentlApp :: Main"!

Pogledajte isprepletene linije: metoda CompoundAssignmentlApp.Get-ArrayElement zapravo se zove dvaput! To je u najmanju ruku neučinkovito, a možda i štetno, ovisno o tome što još metoda radi.

Pogledajmo sada drugi kod koji koristi sintaksu složenog operatora dodjele:

korištenje sustava;

klasa CompoundAssignment2App (

zaštićeni int elementi;

public int GetArrayElementO

povratni elementi;

}

CompoundAssignment2App () (

elementi = novi int;

elemenata = 42;

}

javni statički void Main () (

Aplikacija CompoundAssignment2App = nova CompoundAssignment2App ();

Console.WriteLine ("(0)", app.GetArrayElement ());

app.GetArrayElement () + = 5; Console.WriteLine ("(0)", app.GetArrayElement ()); ))

Korištenje složenog operatora dodjele rezultirat će mnogo učinkovitijim MSIL kodom:

// Učinkovitija tehnika: x op = y.

Metoda public hidebysig static void Main () il upravlja

\ {

\ .ulazna točka

I // Veličina koda 76 (Ox4c) \ .maxstack 4

Lokalno stanovništvo (klasa CompoundAssignmentlApp V_0, int32 V_1) \ IL_0000: newobj instanca void CompoundAssignmentlApp ::. Ctor () \ IL_0005: stloc.O 1 IL_0006: Idstr "(0)" 1 IL_OOOb: ldloc.0 IL_OOOc: poziv instance int32

CompoundAssignmentlApp :: GetArrayElementO IL_0011: Idc.i4.0

IL_0012: Idelema [mscorlib "] System.Int32 IL_0017: okvir [> mscorlib -] System.Int32 lL_001c: call void [" mscorlib "] System.Console :: WriteLine

(klasa System.String, klasa System.Object) IL_0021: ldloc.0 IL_0022: instanca poziva int32

CompoundAssignmentlApp :: GetArrayElement ()

IL_0027: dup

IL_0028: stloc.1

IL_0029: Idc.i4.0

IL_002a: ldloc.1

IL_002b: Idc.i4.0

IL_002c: ldelem.14

IL_002d: ldc.14.5

IL_002e: dodaj

IL_002f: stelem.14

IL_0030: Idstr "(0)"

IL_0035: ldloc.0

IL_0036: pozvati instancu int32

CompoundAssignmentlApp :: GetArrayElementO IL_003b: Idc.i4.0

IL_003c: Idelema ["mscorlib"] System.Int32

IL_0041: okvir [mscorlib "] System.Int32

IL_0046: call void ["mscorlib"] System.Console :: WriteLine

(klasa System.String, klasa System.Object)

IL_004b: ret) // kraj metode "CompoundAssignmentlApp :: Main"

Možete vidjeti korištenu MSIL naredbu dup. Duplicira gornju stavku na stogu, stvarajući tako kopiju vrijednosti koju je metoda vratila CompoundAssignmentlApp.Get element polja. ja

To pokazuje da iako u biti x + = y ekvivalentno x = x + y, MSIL kod je različit u oba slučaja. Ova razlika bi vas trebala natjerati da se zapitate koju sintaksu koristiti u svakom slučaju. Opće pravilo i moja preporuka je da koristite složene operatore dodjele kad god i gdje god je to moguće.

Operatori povećanja i dekrementa

Uveden u C i portiran na C ++ i Java operateri Povećanje 1 i dekrement omogućuju vam da sažeto izrazite da želite povećati ili smanjiti brojčanu vrijednost za 1. To jest, / ++ je ekvivalentno dodavanju 1 trenutnoj vrijednosti / ".

Prisutnost dvaju oblika operatora inkrementa i dekrementa ponekad je zbunjujuća. Prefiks i postfiks tipovi ovih operatora razlikuju se u trenutku u kojem se vrijednost mijenja. U prefiksnoj verziji operatora inkrementa i dekrementa (++ ai - a odnosno) prvo se izvodi operacija, a zatim se stvara vrijednost. U postfix verziji (a ++ i a-) prvo se kreira vrijednost, a zatim se izvodi operacija. Razmotrimo primjer:

korištenje sustava;

klasa IncDecApp (

javna statička praznina Foo (int j)

{

Console.WriteLine ("IncDecApp.Foo j = (0)", j);

>

javni statički void Main () (

int i = 1;

Console.WriteLineC "flo poziva Foo (i ++) = (0)", i);

Console.WriteLine ("Nakon poziva Foo (i ++) = (0)", i);

Console.WriteLine ("\ n");

\ Console.WriteLineC "flo poziva Foo (++ i) = (0)", i);

\ Foo (++ l);

\ Console.WrlteLine ("Nakon poziva Foo (++ i) = (0)", i);

l Rezultat će izgledati ovako:

Prije pozivanja Foo (i ++) = 1

IncDecApp.Foo j = 1

Nakon poziva Foo (i ++) = 2

Prije pozivanja Foo (-n-i) = 2

IncDecApp.Foo j = 3

Nakon poziva Foo (++ i) = 3

Razlika je kada vrijednost se kreira i operand se mijenja. Prilikom pozivanja Foo (i ++) vrijednost /" se prosljeđuje (nepromijenjena) metodi Fuu i nakon metoda return / povećava se za 1. Pogledajte gornji MSIL kod: naredbu dodati izvršava se nakon što se vrijednost gurne na stog.

IL.0013: ldloc.0

IL.0014: dup

IL_0015: Idc.i4.1

IL_0016: dodaj

IL_0017: stloc.O

IL_0018: call void IncDecApp :: Foo (int32)

Pogledajmo sada obrazac prefiks operatora koji se koristi u pozivu Foo (++ a). U ovom slučaju, MSIL kod bit će drugačiji. U ovom slučaju, naredba dodati izvedena prije kako se vrijednost gura u stog za kasnije pozivanje metode Fuu.

IL.0049: ldloc.0

IL_004a: Idc.i4.1

IL_004b: dodaj

IL_004c: dup

IL_004d: stloc.O

IL_004e: call void IncDecApp :: Foo (int32)

Relacijski operatori

Većina operatora vraća numeričke vrijednosti. Što se tiče relacijskih operatora, oni generiraju booleov rezultat. Umjesto / umjesto izvođenja matematičkih operacija nad skupom operanda, / relacijski operatori analiziraju odnos između operanada i povratak značenje pravi, ako je omjer istinit, lažno - ako je / lažno.

Operatori za usporedbu

Za relacijske operatore pozvane operatori usporedbe, referirati) -je "manje" (<), «меньше или равно» (<=), «больше» (>), Veće od ili Jednako (> =), Jednako (==) i Nije jednako (! =). Primjena ovih operatora na brojeve je razumljiva, ali kada se koriste s objektima, njihova implementacija nije tako očita. Evo primjera:

korištenje sustava;

klasa NumericTest (

javni numerički test (int 1)

{

ovo.i = ja;

>

zaštićeni int 1; )

klasa RelationalOpslApp (

javni statički void Main () (

NumericTest testl = novi NumericTest (42); NumericTest test2 = novi NumericTest (42);

Console.WriteLine ("(0)", testl == test2); >)

Ako ste Java programer, znate što će se ovdje dogoditi. Međutim, programeri C ++ će najvjerojatnije biti iznenađeni kada vide rezultat lažno. Dopustite mi da vas podsjetim da kada kreirate instancu objekta, dobivate vezu na nju. To znači da kada naiđe na operator relacije koji uspoređuje dva objekta, C# prevodilac ne uspoređuje sadržaj objekata, već njihove adrese. Da biste to bolje razumjeli, razmotrite MSIL kod:

\ .method public hldebysig static void MainQ il upravljano

\ .ulazna točka

\ // Veličina koda 39 (0x27)

1 .maxstack 3

Lokalno stanovništvo (klasa NumericTest V_0, \ klasa Numerički test V_1, 1 bool V_2)

ILJJOO: Idc.i4.s 42

1L_0002: newobj instanca void NumericTest ::. Ctor (int32)

IL_0007: stloc.O

IL_0008: Idc.i4.s 42

IL_OOOa: newobj instanca void NumericTest ::. Ctor (int32)

IL_OOOf: stloc.1

IL_0010: Idstr "(0)"

IL_0015: ldloc.0

IL_0016: ldloc.1

IL_0017: ekv

IL_0019: stloc.2

IL_001a: Idloca.s V_2

IL_001c: okvir ["mscorlib"] System.Boolean

IL_0021: call void ["mscorlib"] System.Console :: WriteLine

(klasa System.String, klasa System.Object)

IL_0026: ret) // kraj metode "RelationalOpslApp :: Main"

Pogledaj liniju .mještani. Prevoditelj ukazuje da je metoda Glavni tri lokalne varijable. Prva dva su objekti numerički test, treća je booleova varijabla. Sada prijeđimo na linije IL_0002 i IL_0007. Ovdje se instancira objekt testl, i povezivati ​​ga sa stloc je pohranjena u prvoj lokalnoj varijabli. Međutim, važno je da MSIL zadrži adresu novostvorenog objekta. Zatim u redovima IL_OOOa i IL_OOOf vidite MSIL kodove za kreiranje objekata test2 i pohranjivanje vraćene reference u drugu lokalnu varijablu. Konačno, u redovima 1LJ) 015 i IL_0016 lokalne varijable se guraju u stog naredbom idloc, i u redu IL_0017 tim siva uspoređuje dvije vrijednosti na vrhu hrpe (tj. reference objekata testl i testl). Povratna vrijednost pohranjuje se u treću lokalnu varijablu, a zatim se prikazuje metodom Sustav.Konzola. WriteLine.

Ali kako usporediti članove dvaju objekata? Odgovor je korištenje implicitne osnovne klase svih .NET Framework objekata. Naime, za te namjene klas Sustav.Objekat postoji metoda Jednako. Na primjer, sljedeći kod uspoređuje sadržaj objekata i izlaza, kao što biste očekivali, istina: ja

korištenje sustava; /

klasa RelationalOps2App

(/ public static void Main () (

Console.WriteLine ("(0)", testl.Jednako (test2));

Primjer RelationalOpslApp koristi klasu "domaće". (Nu-mericTest) i u drugom primjeru - .NET klasa (Decimal). Poanta je da metoda Sustav.Objekat.Jednako potrebno je nadjačati da bi se napravila stvarna usporedba članova. Stoga metoda Jednako s razredom Nume-ricTest neće raditi jer nismo nadjačali metodu. I evo razreda Decimal poništava metodu koju nasljeđuje jednako, i u ovom slučaju će sve funkcionirati.

Drugi način za usporedbu objekata je korištenje preopterećenje operatera(preopterećenje operatera). Preopterećenje operatora definira operacije koje se izvode na objektima određenog tipa. Na primjer, za objekte niz+ operator ne izvodi zbrajanje, već spaja nizove. Preopterećenje operatera ćemo pokriti u 13. poglavlju.

Jednostavni operatori dodjele

Poziva se vrijednost na lijevoj strani operatora dodjele lvrijednost, a s desne strane - rvalue. Kao rvalue može biti bilo koja konstanta, varijabla, broj ili izraz čiji je rezultat kompatibilan lvrijednost. U međuvremenu lvrijednost mora biti varijabla određenog tipa. Poanta je da se vrijednost kopira s desne strane na lijevu. Stoga se za novu vrijednost mora dodijeliti fizički adresni prostor. Na primjer, možete napisati / "= 4, budući da ima mjesta za / u memoriji - bilo na stogu ili na hrpi - ovisno o vrsti /. A ovdje je operater 4 = 1 ne može se izvršiti jer je 4 vrijednost, a ne varijabla čiji se sadržaj u memoriji može promijeniti. Usput, primijetit ću da u C # kao lvrijednost može biti varijabla, svojstvo ili indekser. Za više informacija o svojstvima i indeksatorima, pogledajte Poglavlje 7. U ovom poglavlju koristim varijable radi jednostavnosti. Ako sa zadatkom brojčane vrijednosti sve je dovoljno jasno, s objektima je kompliciranije. Dopustite mi da vas podsjetim da kada imate posla s objektima, manipulirate stavkama koje se ne slažu i koje je lako kopirati i premještati. U slučaju objekata, zapravo imate samo reference na neke od entiteta za koje se memorija dinamički dodjeljuje. Stoga, kada pokušate dodijeliti objekt (ili bilo koju vrstu reference) varijabli, ne kopiraju se podaci, kao što je slučaj s dimenzionalnim tipovima, već reference.

Recimo da imate dva objekta: testl i test2. Ako navedete testl= test2, testl neće biti kopija test2. Poklopit će se! Objekt testl ukazuje na isto sjećanje kao test2, i sve promjene na objektu testl dovest će do promjena test2. Evo programa koji to ilustrira:

korištenje sustava;

razred Foo (

javni int i; )

klasa RefTestlApp (

javna statička praznina MainO (

Foo testl = novi Foo (); testl.i = 1;

Foo test2 = novi Foo (); test2.i = 2;

Console.WriteLine ("Prije dodjele objekata"); Console.WriteLine ("test1.i = (0>", testl.i); Console.WriteLine ("test2.i = (0)", test2.i); Console.WriteLine ("\ n");

testl = test2;

Console.Writel_ine ("Nakon dodjele objekata");

Console.WriteLine ("test1.i = (0)", testl.i); Console.WriteLine ("test2.i = (0)", test2.i); Console.WriteLine ("\ n");

testl.i = 42; ;"

Console.WriteLine ("Nakon promjene samo člana TEST1"); Console.WriteLine ("test1.i = (0)", testl.i); Console.WriteLine ("test2.i = (0)", test2.i); Console.WriteLine ("\ n"); ))

Pokretanjem ovog koda vidjet ćete:

Prije dodjele objekta

test1.i = 1

test2.i = 2

Nakon dodjele objekta

testt.i = 2

test2.i = 2

Nakon promjene samo člana TEST1

test1.i = 42

test2.i = 42

Pogledajmo što se događa u svakoj fazi ovog primjera. Foo - to je jednostavna k klasa sa samo jednim članom, /. U metodi Main kreiraju se dvije instance ove klase: testl i test2- i njihovi članovi i postavljeni su na 1 odnosno 2. Ove vrijednosti se zatim izlaze, i prema očekivanjima testl.i jednako 1, a test2.i- 2. I tu počinje zabava! V sljedeći redak objekt testl dodijeljena test2.Čitatelji Jave znaju što je sljedeće. Međutim, većina C++ programera će očekivati ​​člana/objekt testl je sada jednak članu objekta test2(pod pretpostavkom da će se prilikom prevođenja takve aplikacije izvršiti neka vrsta operatora za kopiranje članova objekta). Čini se da prikazani rezultat to potvrđuje. Međutim, u stvarnosti, veza između objekata sada je mnogo dublja. Članu dodijelite vrijednost 42 testl.i i ponovno ispišite rezultat. I?! Kada se objekt promijeni testl promijenio i testZ To se dogodilo zbog činjenice da je objekt testl ne više. Nakon što ga dodijeli test2 objekt testl je izgubljen jer ga aplikacija više ne referencira i kao rezultat ga "čisti" sakupljač smeća (GC). Sada testl i test2 pokažite na istu memoriju na hrpi. Stoga, kada se promijeni jedna varijabla, korisnik će vidjeti i drugu promjenu.

Primijetite da se ispisuju zadnja dva retka: iako se samo vrijednost promijenila u kodu testl.i, značenje test2.i također promijenio. Još jednom, obje varijable sada upućuju na istu memorijsku lokaciju - to je ponašanje koje bi Java programeri očekivali. Međutim, to uopće ne ispunjava očekivanja C++ programera, budući da se u ovom jeziku izvodi kopiranje objekata: svaka varijabla ima svoju jedinstvenu kopiju svojih članova i promjene na jednom objektu ne utječu na drugi. Budući da je ovo ključ za razumijevanje kako objekti rade u C #, hajde da malo odmaknemo i vidimo što se događa kada objekt proslijedite metodi:

korištenje sustava;

razred Foo (

javni int i; )

klasa RefTest2App (

public void ChangeValue (Foo f)

{

f.i = 42;

}

javni statički void Main () (

Aplikacija RefTest2App = nova RefTest2App ();

Foo test = novi Foo (); test.i = 6;

Console.WriteLine ("Prije pozivanja metode"); Console.WriteLine ("test.i = (0)", test.i); Console.WriteLine ("\ n");

app.ChangeValue (test);

Console.WriteLine ("Nakon pozivanja metode"); Console.WriteLine ("test.i = (0)", test.i); Console.WriteLine ("\ n"); >)

U većini jezika osim Jave, ovaj će kod kopirati stvoreni objekt testirati u lokalni skup metoda RefTest2App.ChangeValue. U ovom slučaju, objekt test, stvorena u metodi Glavni, nikada neće vidjeti promjene u objektu / napravljene u metodi ChangeValue. Međutim, još jednom ponavljam da je metoda Glavni prosljeđuje referencu na objekt dodijeljen hrpi test. Kada je metoda Promjena vrijednosti manipulira svojom lokalnom varijablom //, također izravno manipulira objektom test metoda Glavni.

Hajde da rezimiramo

Glavna stvar u bilo kojem programskom jeziku je način na koji se obavlja dodjela, matematičke, logičke i relacijske operacije - sve što je potrebno za rad. stvarne aplikacije... U kodu su te operacije predstavljene operatorima. Čimbenici koji utječu na izvršavanje operatora uključuju prioritet i asocijativnost (desno i lijevo) operatora. Snažan skup unaprijed definiranih operatora u C # može se proširiti korisnički definiranim implementacijama, o čemu ćemo govoriti u 13. poglavlju.

Posljednje ažuriranje: 19.06.2017

Uvjetni izrazi su zaseban skup operacija. Takve operacije vraćaju booleovu vrijednost, odnosno vrijednost tipa bool: true ako je izraz istinit i false ako je izraz lažan. Takve operacije uključuju usporedbu i logičke operacije.

Operacije usporedbe

Operacije usporedbe uspoređuju dva operanda i vraćaju bool vrijednost — true ako je izraz istinit, i false ako je izraz netočan.

    Uspoređuje dva operanda radi jednakosti. Ako su jednaki, tada operacija vraća true, ako nisu jednaki, onda se vraća false:

    B; // lažno

    Uspoređuje dva operanda i vraća true ako operandi nisu jednaki i false ako su jednaki.

    Int a = 10; int b = 4; bool c = a! = b; // istina bool d = a! = 10; // lažno

    Manje od operacije. Vraća true ako je prvi operand manji od drugog i false ako je prvi operand veći od drugog:

    Int a = 10; int b = 4; bool c = a< b; // false

    Veće od operacije. Uspoređuje dva operanda i vraća true ako je prvi operand veći od drugog, inače vraća false:

    Int a = 10; int b = 4; bool c = a> b; // istina bool d = a> 25; // lažno

    Manje ili jednako operaciji. Uspoređuje dva operanda i vraća true ako je prvi operand manji ili jednak drugom. Inače vraća false.

    Int a = 10; int b = 4; bool c = a<= b; // false bool d = a <= 25; // true

    Veće ili jednako operaciji. Uspoređuje dva operanda i vraća true ako je prvi operand veći ili jednak drugom, inače vraća lažno:

    Int a = 10; int b = 4; bool c = a> = b; // istina bool d = a> = 25; // lažno

Operacije<, > <=, >= ima prednost nad == i! =.

Logičke operacije

C # također definira logičke operatore koji također vraćaju bool vrijednost. Uzimaju bool vrijednosti kao operande. Obično se primjenjuju na odnose, kombiniraju više operacija usporedbe.

    Logički zbrajanje ili logičko ILI. Vraća true ako barem jedan od operanada vraća true.

    Bool x1 = (5> 6) | (4< 6); // 5 >6 - lažno, 4< 6 - true, поэтому возвращается true bool x2 = (5 >6) | (4> 6); // 5> 6 - netočno, 4>

    Logičko množenje ili logička operacija I Vraća true ako su oba operanda istovremeno istinita.

    Bool x1 = (5> 6) & (4< 6); // 5 >6 - lažno, 4< 6 - true, поэтому возвращается false bool x2 = (5 < 6) & (4 < 6); // 5 < 6 - true, 4 < 6 - true, поэтому возвращается true

    Operacija logičkog zbrajanja. Vraća true ako barem jedan od operanada vraća true.

    Bool x1 = (5> 6) || (4< 6); // 5 >6 - lažno, 4< 6 - true, поэтому возвращается true bool x2 = (5 >6) || (4> 6); // 5> 6 je netočno, 4> 6 ​​je netočno, pa se vraća false

    Logička operacija množenja. Vraća true ako su oba operanda istovremeno istinita.

    Bool x1 = (5> 6) && (4< 6); // 5 >6 - lažno, 4< 6 - true, поэтому возвращается false bool x2 = (5 < 6) && (4 < 6); // 5 < 6 - true, 4 >6 je istina, pa se vraća true

    Operacija logičke negacije. Izvodi se na jednom operandu i vraća true ako je operand lažan. Ako je operand istinit, tada operacija vraća false:

    Bool a = istina; bool b =! a; // lažno

    Ekskluzivna operacija ILI. Vraća true ako su prvi ili drugi operand (ali ne oba) istiniti, inače vraća false

    Bool x5 = (5> 6) ^ (4< 6); // 5 >6 - lažno, 4< 6 - true, поэтому возвращается true bool x6 = (50 > 6) ^ (4 / 2 < 3); // 50 >6 - istina, 4/2< 3 - true, поэтому возвращается false

Ovdje imamo dva para operacija | i || (kao i & i &&) rade slične stvari, ali nisu iste.

U izrazu z = x | y; izračunat će se i x i y.

U izrazu z = x || y; prvo će se izračunati vrijednost x, a ako je točna, onda izračunavanje vrijednosti y nema smisla, jer će u svakom slučaju z već biti jednako istinito. Y će se izračunati samo ako je x lažno

Isto vrijedi i za & / && par operacija. Izraz z = x procijenit će i x i y.

U izrazu z = x & prvo će se izračunati vrijednost x, a ako je netočna, onda izračun vrijednosti y više nema smisla, jer će u našem slučaju u svakom slučaju z već biti jednak na lažno. Vrijednost y će se izračunati samo ako je x istinito

Dakle, operacije || i && su prikladniji u izračunima, jer vam omogućuju smanjenje vremena za procjenu vrijednosti izraza, a time i povećanje performansi. I operacije | i & su prikladniji za izvođenje bitnih operacija nad brojevima.

Operator && ima prednost nad operatorom ||. Dakle, u izrazu istina || true && false, prvi se izvršava podizraz true && false.

Vrhunski povezani članci