Objavljeno: 3.1.2008 15:56 | Avtor: David Vidmar | Monitor December 2007

Kaj je novega v C# 3.0

Po trenutnih napovedih, lahko konec meseca novembra pričakujemo izid Microsoft Visual Studio 2008, ki prinaša številne novosti in hkrati precej zmede zaradi neposrečenega številčenja različic tehnologij. Tokrat si bomo površno pogledali, kaj prinaša osveženi jezik Visual C#, ki bo nosil oznako 3.0, naslednjič pa se bomo posvetili novostim razvojnega okolja Visual Studio.

V prihajajoči različici 3.0 so Microsoftovi arhitekti jezik C# nadgradili z nekaterimi konstrukti, ki kodo naredijo kompaktnejšo, kar naj bi razvijalcem omogočilo večjo produktivnost. Novosti je peščica, večina sprememb pa je bila potrebna za izvedbo poglavitne novosti v prihajajoči platformi Microsoft .NET Framework 3.5 - LINQ oz. Language Integrated Query. Oglejmo si jih po vrsti od bolj splošnih do tesno vezanih na LINQ.

Auto-Implemented Properties

V dosedanjih različicah C# smo razvijalci veliko kode porabili za napoved enostavnih lastnosti razreda (properties):

private string ime;

public string Ime2

{

get

{

return ime;

}

set

{

ime = value;

}

}

Zgornja koda ne vsebuje nobene logike, npr. za preverjanje vrednosti pred prirejanjem. Neizkušeni razvijalec bo seveda takoj vprašal, zakaj ne naredimo raje kar javnega polja (public field), vendar bo bolj izkušeni takoj odvrnil, da je to nujno zaradi podatkovnega spajanja (databinding), serializacije in ker tako ne bi mogli pozneje dodati logike pri prirejanju, ne da bi znova prevedli tudi programe ali knjižnice, ki bi tako kodo uporabljali.

Do neke mere smo lahko razvoj pohitrili z generiranjem kode, raznimi vtičniki za Visual Studio ali izrezki (snippets), vendar je koda kljub vsemu preobširna in kar kliče po poenostavitvi.

V C# 3.0 lahko vsebinsko enakovredno kodo zapišemo do skrajnosti poenostavljeno:

public string Ime { get; set; }

Ljubitelji zelo kompaktne kode pa bodo lahko to zapisali celo v eno samo vrstico, pa bo koda še vedno pregledna! Ko bomo potrebovali logiko, jo bomo enostavno dodali, navzven pa se razred ne bo spremenil.

Object Initializers, Collection Initializers

Vzpostavljanju predmetov v C# pogosto sledi nastavljanje lastnosti novega izvoda. Razvijalci precej pogosto pišemo kodo, kot je ta:

Oseba oseba = new Oseba();

oseba.Ime = "David";

oseba.Priimek = "Vidmar";

oseba.Starost = 31;

Po novem jo bomo lahko zapisali v nekoliko nenavadni skladnji, a bistveno krajše:

Oseba oseba = new Oseba { Ime = "David", Priimek = "Vidmar", Starost = 31 };

Že z novim načinom vzpostavljanja predmetov prihranimo nemalo vrstic kode. Če pa podobno skladnjo uvedemo še na seznamih, so prihranki še večji.

List<Oseba> osebe = new List<Oseba> {

new Oseba { Ime = "David", Priimek = "Vidmar", Starost = 31 },

new Oseba { Ime = "Jure", Priimek = "Vidmar", Starost = 54 },

new Oseba { Ime = "Tilen", Priimek = "Vidmar", Starost = 31 }

};

Extension Methods

Po novem lahko v C# v slogu novodobnih dinamičnih jezikov dodajamo metode razredom, ne da bi morali spreminjati njihovo izvorno kodo. Oglejmo si primer:

public static bool JeVeljavenEPostniNaslov(this string s)

{

Regex regex = new Regex(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$");

return regex.IsMatch(s);

}

Če napovemo metodo na ta način, smo narediti t. i. "Extension Method" za razred String. Zdaj lahko to metodo uporabimo tako, kot da bi bila del tega razreda, ki ga sicer seveda nikakor ne bi mogli spremeniti.

string eposta = "moj e-mail";

if (eposta.JeVeljavenEPostniNaslov())

{

/* ... */

}

Ta novost omogoča precej zanimive pristope k reševanju problemov, verjetno pa bo botrovala tudi kakemu zmazku, saj je z nepremišljeno uporabo mogoče napisati zelo nepregledno kodo.

LINQ se močno opira na Extension Methods, saj je bilo tako mogoče standardne knjižnice, recimo System.Xml, nadgraditi, ne da bi se te pravzaprav spremenile.

Partial Method Definitions

V C# 2.0 smo dobili zelo koristno novost, imenovano delni razredi (partial classes). Ti nam omogočajo, da kodo razreda razbijemo na dve ali več izvornih datotek. To se izkaže za zlata vredno pri kakršnemkoli generiranju izvršne kode. Spreminjanje generirane kode je namreč precej nevarna reč, saj lahko te spremembe kaj hitro izgubimo, če pa jih zapisujemo v ločeno datoteko, ta težava odpade.

Delne metode so tesno povezane z delnimi razredi, saj se lahko pojavljajo le v takih razredih. Omogočajo, da v eni izvorni datoteki napovemo obstoj metode, izvedemo pa jo v drugi. Veljajo seveda nekatere omejitve, saj so vse metode privzeto zasebne, ne morejo vračati vrednosti in tako naprej.

Napoved delne metode je videti takole:

partial void PrimerDelneMetode(string vrednost);

Izvedba delne metode pa:

partial void PrimerDelneMetode(string vrednost)

{

// realizacija metode

}

Delne metode imajo podoben namen kakor delni razredi - poenostaviti nekatere scenarije pri generiranju kode ali kode v več datotekah. Delno metodo si lahko predstavljamo kot nekakšen vzorec, saj nam Visual Studio oz. IntelliSense ob pisanju izvedbe pomaga nekako tako, kot če bi metodo nasledili od prednika.

Lambda Expressions

V C# 2.0 smo dobili t. i. anonimne metode, ki so omogočale, da kar na mestih, na katerih smo v C# 1.0 uporabili delegate, zapišemo kodo. Izrazi lambda omogočajo funkcionalen zapis anonimnih metod. To je zelo uporabno - uganili ste! - pri uporabi poizvedb LINQ.

V C# 2.0 smo morali metodo, ki sprejema "delegate", zapisati takole:

osebe.Where(delegate(Oseba o)

{

return o.Priimek == "Vidmar";

});

V C# 3.0 pa lahko enakovredno kodo zapišemo veliko krajše:

osebe.Where(o => o.Priimek == "Vidmar");

Iz primera je razvidno, da je izraz lambda sestavljen iz parametrov, ki jim sledi operator => in nato izraz ali blok, ki se izvede ob izračunavanju vrednosti izraza lambda.

Verjetno bo trajalo nekaj časa, da se bo novost prijela pri razvijalcih in da se jo bomo navadili uporabljati. Pri uporabi LINQ pa jo bomo uporabljali in najverjetneje pozabili, da se sintaksa imenuje izraz lambda.

Implicitly Typed Local Variables

Ko napovemo krajevno spremenljivko in namesto tipa zapišemo besedico var namesto tipa, smo s tem prevajalniku naročili, naj ugotovi tip iz izraza, ki ga spremenljivki prirejamo. Naj kar takoj poudarimo, da to NI tip variant, ki ga pozna Visual Basic ali JavaScript. Spremenljivka je še vedno močnega tipa, le da tip izbere prevajalnik na podlagi izraza, ki ga spremenljivki prirejamo. Tip se torej ne določa med izvajanjem, temveč ob prevajanju.

private void PrimerVar() {

var i = 5;

var s = "Hello";

i = s;

}

Spremenljivka i iz prve vrstice primera je tipa "int", druga pa "string". Če bi bila spremenljivka vrste Variant, bi bila tretja vrstica veljavna, pa ni. Prevajalnik bo v tretji vrstici opozoril, da tipa string ni mogoče implicitno pretvoriti v tip "int".

Anonymous Types

Anonimni tipi ponujajo možnost, da razvijalec v kodi definira razred, ne da bi za to potreboval formalno deklaracijo tega razreda.

Anonimni tipi so močno povezani s spremenljivkami implicitnega tipa var in seveda z LINQ. Če zaenkrat še odmislimo poizvedbo LINQ, si oglejmo primer anonimnega tipa.

var proizvodi =

from p in db.Products

where p.UnitPrice > 50

select new

{

Id = p.ProductId,

Name = p.ProductName,

LastFiveOrder = p.OrderDetails.Take(5)

};

Iz zgleda vidimo, da je novi razred definiran z vrsticami znotraj bloka, ki sledi "select new", in ker smo uporabili spremenljivko implicitnega tipa, bo prevajalnik sam izbral ustrezen tip spremenljivke. Zdaj vidimo, da brez spremenljivk "tipa" var LINQ sploh ne bi bil mogoč.

Query Syntax, Query Keywords

Nove rezervirane besede so srce LINQ. S temi rezerviranimi besedami lahko zapišemo poizvedbo LINQ. Nove, v marsičem revolucionarne tehnologije LINQ seveda ne moremo opisati v teh nekaj vrsticah, zato priporočamo vsem zainteresiranim, da pobrskajo po spletu ali si priskrbijo katero izmed številnih knjig, celo vsak dan jih je več. Mi pa si bomo LINQ ogledali samo od daleč.

LINQ nam omogoča, da neposredno v izvorni kodi zapišemo poizvedbo nad podatki. Poizvedujemo lahko po objektih, ki temeljijo na IEnumerable<T>, sočasno pa je arhitektura odprta za dodatne ponudnike (providers). Privzeto bo Visual Studio 2008 vseboval ponudnike (providers) za zbirke podatkov SQL, ADO.NET razred DataSet in dokumente XML. Torej bo mogoče z enako skladnjo izvajati poizvedbe povsem različnih izvorih podatkov, ne da bi se za vsakega morali učiti novega poizvedbenega jezika. Za pretvorbo v jezik SQL ali XPath bo poskrbel ponudnik.

Nove rezervirane besede so tako from, where, select, group, into, orderby, join in let. Ne da bi se preveč ukvarjali z vsemi podrobnostmi, si oglejmo zelo enostavno poizvedbo LINQ izvedeno nad zbirko podatkov SQL:

Customers custQuery =

(from custs in db.Customers

where custs.CustomerID == "BONAP"

select custs)

.First();

Če namignemo še, da gre za poizvedbo nad zdaj že legendarno vzorčno zbirko podatkov Northwind, potem je primer lahko razumeti. Iz tabele strank bo izbral prvo stranko s podanim ključem.

Dolžni smo še razlago poizvedbe iz prejšnjega poglavja. Ta bo iz tabele izdelkov izbrala vse, ki so dražji od 50 enot, in vrnila seznam, ki bo vseboval šifro izdelka, ime izdelka in seznam zadnjih petih postavk naročil. Kar zapleten opis za razmeroma enostavno zapisano poizvedbo!

Če vas bodo poizvedbe LINQ spominjale na SQL, seveda niste dosti zgrešili. Naj še enkrat poudarimo, da jih je mogoče izvajati tako nad predmeti v delovnem pomnilniku kot podatkovnimi skladišči, datotekami XML, programerji po svetu pa so že napisali množico drugih dobaviteljev, recimo za trgovino Amazon, imenik LDAP in številne izdelke OR/M.

C# 2.0 + LINQ = C# 3.0

Ne bomo preveč zgrešili, če bomo kar vse novosti v jeziku pripisali želji, a bi naredili LINQ čim bolj integriran v sam jezik, hkrati učinkovit in enostaven. Kljub temu bomo lahko nekatere novosti, sploh tiste z začetka članka, s pridom uporabili tudi, če se (še) ne bomo dotaknili LINQa.

LINQ je nedvomno velika novost. Del zainteresirane javnosti je zelo navdušen, je pa seveda tudi nekaj skepse. Kot velja za vse tehnologije, tudi LINQ ne bo rešil vseh težav, nedvomno pa bo omogočal nadvse elegantne rešitve nekaterih problemov. Arhitekti in razvijalci pa imamo odgovornost, da bomo tehnologijo uporabljali le tam in tako, kot je smiselno, ne pa za vsako ceno, kot se dandanes dogaja z novimi in razvpitimi tehnologijami.

Ne priporočamo vam, da bi skočili na LINQ kar ta hip in pozabili vse druge, ki ste jih s pridom uporabljali do zdaj. Prav tako kot vam ne priporočamo, da ga povsem spregledate. Spoznajte ga, sami ugotovite, kaj so njegove prednosti in kaj slabosti, in ga dodajte v svoj nabor znanja. Kmalu boste že od daleč vedeli, kdaj omogoča boljšo, hitrejšo in/ali cenejšo rešitev. To pa je ne nazadnje tudi pravi namen tehnologije.

Najpomembneje je razumeti, da bomo lahko programe še vedno poganjali v skupnem izvajalnem okolju (CLR) različice 2.0 in ne bo treba namestiti novih. Če bomo v programih uporabljali nove tehnologije, bo treba z našo aplikacijo namestiti le knjižnice teh!

Zmeda s številkami

Visual Studio 2008 - Z različico razvojnega okolja Visual Studio ni težav. Različica 2008 prinaša novosti in izboljšave in bo nasledila različico 2005.

C# 3.0 - nova različica jezika Visual C#

VB 9.0 - nova različica jezika Visual Basic.NET

Microsoft .NET Framework 3.5 - Skupno ime za celoten .NET paket tehnologij in izdelkov. Številka različice je povsem ponesrečena, saj Microsoft .NET Framework 3.5 "sestavljajo":

  • izvajalno okolje Common Language Runtime (CLR) 2.0,
  • jezika Visual C# 3.0 in Visual Basic.NET 9.0,
  • dodatki za CLR, ki jih je dodal Microsoft .NET Framework 3.0, torej Windows Presentation Foundation (WPF), Windows Communication Foundation (WCF), Windows Workflow Foundation (WWF) in CardSpaces,
  • Naroči se na redna tedenska ali mesečna obvestila o novih prispevkih na naši spletni strani!

    Komentirajo lahko le prijavljeni uporabniki

     
    • Polja označena z * je potrebno obvezno izpolniti
    • Pošlji