A C# programozási nyelv

C# 4.5 Újdonságok

Bevezető

Amikor a C# nyelv egy új változatát említjük igazából a kód futtatásához nélkülözhetetlen .NET keretrenszer verziójáról van szó, hiszen ez szabja meg, hogy milyen utasításkészlettel dolgozhatunk. A keretrendszer jelenleg a 4.5-ös főverziónál tart. Ez a verzió 2012 nyarán a Visual Studio 2012 megjelenésével majdnem egy időben lett publikálva. Azóta megjelent két kiegészítés is a keretrendszerhez: 2013 őszén a Visual Studio 2013-al karöltve a 4.5.1-es verzió, majd mindössze néhány hete (2014. május) a 4.5.2-es verzió. A következőkben ezeknek a legfontosabb újdonságaikról szeretnék írni.
A .NET 4.5-nek talán a legfontosabb újítása talán a Metro felületi alkalmazások támogatásához szükséges funkciók voltak, de számos további újítás található benne, mint fejlettebb erőforrás kezelés, párhuzamosság támogatásának új módjai, aszinkron fájl műveletek, a konzolos felülethez Unicode (UTF-16) karakterkódolás támogatása, különböző kultúrák formátumaink támogatása (dátum formátuma stb.) , HTTP fájlrendszer támogatásának és egyéb hálózati műveletek használatának könnyítése, néhány újdonság a WPF-hez és az ASP.NET-hez illetve a WCF-hez, az utóbbinál legfontosabb a konfiguráció könnyítése.
A következőkben ezek körül szeretnék írni a fontosabbnak, hasznosabbnak tűnőekről, de minden megtalálható részletesen a következő webcímen: http://msdn.microsoft.com/en-us/library/ms171868(v=vs.110).aspx

Alapvető változások a keretrendszerben

Sok apróság változott a keretrendszerben, ami kellemesebbé teszi az életünket. Rögtön az elején egy ilyen, hogy a keretrendszer telepítője a korábbiakkal ellentétben mindent megtesz annak érdekében, hogy amikor a keretrendszert telepítjük ne kelljen újraindítani számítógépünket. Alapvetően azért kellhet újraindítani, mert ilyenkor a korábbi verziójú .NET keretrendszert írjuk felül, viszont azt könnyen lehetséges, hogy más programok használják. A 4.5-ös változat telepítője ahelyett, hogy újraindításra szólítana fel minket inkább feltérképezi ezen programokat és ezen progamok bezárására kér meg minket.
Másik apró kellemesség, hogy az új verzióban már lehetőségünk van 2 gigabájtnál nagyobb tömbökkel is dolgozni, de ahhoz, hogy ezt megtegyük ezt jeleznünk kell a Garbage Collector-nak olyan módon, hogy a config fájlban elhelyezzük a következő sort:
Amire itt oda kell figyelnünk az egyik, hogy ilyen nagy adatszerkezettel csak különösen indokolt esetben érdemes dolgoznunk, a másik hogy a tömb maximális elemszáma így is az Uint32 maximális értéke, azaz 4,294,967,295, illetve még arra, hogy ez a beállítása a stringek és az egyéb elemek maximális méretét nem befolyásolja.

Alapvető nyelvi változások

A nyelvi elemeknél számos apróbb változatás történt, ilyen például az, hogy a reguláris kifejezéseknek megadhatunk maximális futási időt. A reguláris kifejezésnek ilyenkor meg kell adni a konstruktorban egy Timespan típusú értéket és ha reguláris kifejezés végrehajtása ennél több ideig tart, akkor egy RegexMatchTimeoutException típusú kivétel váltódik ki.

CultureInfo használata

Újdonság szintén a több nyelvet támogató programok készítését nagy mértékben segítő CultureInfo osztály. A keretrendszerben számos előre defíniált formátum lézeik, egy-egy ilyen formátum egy-egy nemzethez illetve nyelvhez tartozik és magában foglalja az adott nyelvben használt dátumformátumot, számok formátumát stb. Így könnyedén elérhetjük, hogy a programunkban minden dátum stb. magyar (vagy éppen angol/német stb.) formátumban jelenjen meg programunkban. Egy formátumcsomag betöltését szálanként tehetjük meg, azaz a programunkban minden Thread-re egyesével kell beállítani a következő módon:
Thread.CurrentThread.CurrentCulture = new CultureInfo("hu-HU");
Azaza threadnek van egy CurrentCulture nevű tulajdonsága és ehhez kell egy új CultureInfo-t létrehoznunk, amelynek paraméterként meg kell adnunk az adott nyelv azonosítóját, ez a magyar esetében hu-HU, angol esetében en-US, a többi nyelv esetében hasonlóan képezhető. Ha az adott szálból GUI-ra is szeretnénk írni akkor annak a CurrentUICulture tulajdonságát is hasonló módon kell beállítanunk. Nézzük a következő programot:
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
			double d = 25.342;
			Console.WriteLine(d);
			Console.WriteLine(DateTime.Now);
			Console.ReadLine();
Most a következő eredményt adja:
25.342
			5/17/2014 8:32:49 PM
Míg ha a CultureInfo eredményeként azt adjuk meg, hogy hu-HU, akkor az eredmény a következő lesz:
25,342
			2014.05.17. 20:33:49

Aszinkron fájlműveletek

A Windows RT-s alkalmazásoknál a korábban megszokott fájlműveleteket új, aszinkron fájlműveletek váltják fel, rá vagyunk kényszerítve ezek használatára. Ezeket a műveleteket természetesen nem csak Windows RT-s alkalmazások esetében használhatjuk.
Az aszinkron fájlkezelés célja az, hogy ne kelljen megakasztanunk a programunk futását a sokszor sok időt igénylő fájlműveletek esetében, ez főleg azért fontos, mert ilyenkor az UI-t is megakasztjuk. Inkább végezzük el azt aszinkron módon, azaz ne várjuk meg feltétlenül a lefutásuk végét. Az aszinkron fájlműveleteknél a következő függvényeket használhatjuk: ReadAsync, WriteAsync, CopyToAsync, FlushAsync, ReadLineAsync, és ReadToEndAsync. Az, hogy mire való az nagyjából értelemszerű: a ReadAsync fájlból olvasásra, a WriteAsync fájlba írásra, a CopyToAsync fájltartalom másolására, a FlushAsync a bufferek űrítésére, a ReadLineAsync a sor végéig tartó olvasásra míg a ReadToEndAsync a fájl végéig tartó olvasásra.
Fontos, hogy az aszinkron műveletet is tartalmazó függvényeket meg kell jelölni az async kulcsszóval. Még egy további új kulcsszó jött képbe az aszinkron hívásokkal kapcsolatban, ez pedig az await kulcsszó, amelynek segítségével azt érhetjük el, hogy a programunk futása megvárja az aszinkron hívás végét.
Példakód egy mappában lévő fájlok egy másik mappába másolására aszinkron fájlműveletek segítéségével:
string StartDirectory = @"c:\Users\exampleuser\start";
			string EndDirectory = @"c:\Users\exampleuser\end";

			foreach (string filename in Directory.EnumerateFiles(StartDirectory))
			{
				using (FileStream SourceStream = File.Open(filename, FileMode.Open))
				{
					using (FileStream DestinationStream = File.Create(EndDirectory + filename.Substring(filename.LastIndexOf('\\'))))
					{
						await SourceStream.CopyToAsync(DestinationStream);
					}
				}
			}

Párhuzamosság újfajta támogatásai

A .NET 4.5 számos olyan újítást tartalmaz, amely a párhuzamos programok készítését segíti elő. Ezek vagy már korábban is meglévő osztályok továbbfejlesztései vagy teljesen új megközelítések. Ezekről szeretnék néhány szót írni.
Meg kell említenem, hogy a már korábban is meglévő Task Paralell Library is komoly fejlesztéseket végeztek el, de kódolás közben ebből semmit sem veszünk észre, a tagfüggvények és az osztálynevek nem változtak, viszont a végrehajtás gyorsasága a korábbi többszöröse lett.
Szintén komoly fejlesztéseket eszközöltek a LINQ lekérések párhuzamosításakor. Ilyenkor szintén észre sem vesszük mi programozóként, hogy igazából a háttérben párhuzamos programfutás történik, legfeljebb annyit veszünk észre, hogy a kódból készült program a korábbinál gyorsabban fut le.
Már a .NET 4.0-ban megjelent a CanellationTokenSource amellyel megszakíthatjuk a taszkok futását. A .NET 4.5-ben már lehetőségünk van mindezt időzítve is megtenni a következő kód segítségével:
var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token;
A párhuzamossággal kapcsolatos további fontos újítás az aszinkron metódusok bevezetése, de erről már fentebb az aszinkron fájlműveleteknél volt szó.
Illetve fontos az is, hogy a Visual Studio 2012-ben már jóval nagyobb a támogatottsága a párhuzamos programok debug-olásának, ezt segíti elő például a Parallel Watch ablak.

Hálózati műveletekkel kapcsolatos új funkciók

Számos fejlesztés történt a különböző hálózati protokolokkal kapcsolatos osztályok esetében is. Bejött egy teljesen új névtér System.Web.HTTP néven, amely a HTTP kérésekkel kapcsolatos funkciókat gyűjti egybe. A névtérben annyi osztály van, hogy mindet bemutatni terjedelmi okokból most nincs lehetőségem, de bármilyen HTTP protokollal kapcsolatos művelet egyszerűen elvégezhető. Például a HttpListener osztály segítségével bármikor néhány sorból fellőhetünk egy HTTP szervert.
Példaként egy egyszerű HTTP szerver kódja:
if (prefixes == null || prefixes.Length == 0)
				throw new ArgumentException("prefixes");
			HttpListener listener = new HttpListener();
			foreach (string s in prefixes)
			{
				listener.Prefixes.Add(s);
			}
			listener.Start();
			Console.WriteLine("Listening...");
			HttpListenerContext context = listener.GetContext();
			HttpListenerRequest request = context.Request;
			HttpListenerResponse response = context.Response;
			string responseString = " Hello world!";
			byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
			response.ContentLength64 = buffer.Length;
			System.IO.Stream output = response.OutputStream;
			output.Write(buffer,0,buffer.Length);
			output.Close();
			listener.Stop();
			

Új projekttípusok

Szintén meg kell említeni az új project típus, a Windows Store Application bevezetését, amely értelemszerűen a „csempés” alkalmazások létrehozására alkalmas.
Szintén új projekttípus a Portable Class Library, amely egy olyan osztálykönyvtár, amelyet különböző .NET verziójú programokban is felhasználhatunk.