K sepsání tohoto článku mě vedlo z velké části to, že za poslední 2 měsíce jsem ve VB.NET nenapsal ani řádku a píšu všechno v C#. Dělám na projektu s několika lidmi, a tento projekt je v C#. Musím říct, že jsem si na C# zvyknul a platformu .NET bych v současnosti nevyměnil za nic na světě. Existuje ale několik málo věcí, které mě na jazyce C# štvou a díky kterým se u programování vztekám. Ve VB.NET jsem tyhle problémy prostě neměl, nemůžu si pomoct.
Neduh číslo 1 - o svých chybách chci vědět hned
Tohle je poměrně známá věc a zhruba před 2 lety jsem na blogu vývojářů VB.NET četl na toto téma pěkný článek. Když píšete ve VB.NET, uděláte na řádku nějakou chybu a pak zmáčknete ENTER, ihned na vás vyskočí hláška, pokud je na řádku nějaká chyba (a to jakákoliv chyba, ne jen chybějící závorka nebo středník, které jsou v C#). Je pravda, že ve VB6 vyskočil opravdu MessageBox, což bylo dost otravné a byla to první věc, kterou jsem po nainstalování vypínal v nastavení. Ve VB.NET se jenom dole v podokně Error List objeví řádek, že máte něco špatně. Na tohle si člověk zvykne hodně rychle a je to mimořádně pohodlné. Chybu můžete opravit hned, jak nastane, a neuděláte ji na deseti dalších místech.
V C# se vám všechny chyby objeví až ve chvíli, kdy zmáčknete Ctrl-Shift-B, tedy Build, případně F5. Je pravda, že když na řádku použijete proměnnou, kterou chcete v zápětí o tři řádky výše nadeklarovat (někdo holt píše kód odzadu :-), hází na vás VB.NET hned chybové hlášky, kdežto C# vás nechá být. Ale pak se vám stane, že čekáte, že vám nějaká funkce, kterou jste psali před měsícem, vrací pole objektů Segment, ale ona ve skutečnosti vrací List<Segment>. Nu což, kompilátor nic neřekne, takže si napíšete několik delegátů a spoustu funkcí, které chtějí pole, a pak na vás v nestřeženém okamžiku vybafne 30 chyb. Pro ty, kteří by mi poradili, abych na výsledek funkce jednoduše zavolal ToArray, čímž bych z Listu udělal pole, musím připomenout, že o metodě ToArray vím a nepoužil jsem ji, protože vnitřně kopíruje celé pole, což se mi zrovna nehodí.
A navíc pak ještě zapomenete projekt buildnout a hned ho check-innete na Team Foundation Server i s chybami a ráno vám všichni nadávají, že jim to nejde zkompilovat. Já vím, dá se TFS nastavit tak, aby tohle nepovolil, ale my to nastavené zrovna nemáme. Ve VB.NET se tohle stát nemůže, o svých chybách vím prostě hned.
Neduh číslo 2 - přetypováváme jako o život
Ve svém projektu mám strukturu Vector3D, která má jednoduše 3 public proměnné typu float - X, Y a Z. Property jsem v tomto konkrétním případě nedělal (ony tam vlastně původně byly a pak jsem je dal pryč). No, jak spočítat délku toho vektoru? Přes Pythagorovu větu, že? No nic, tak napíšeme readonly vlastnost Length, která vrátí délku:
return Math.Sqrt(X * X + Y * Y + Z * Z);
No tohle samozřejmě nejde, že? Protože Math.Sqrt vrací double. Jenže já potřebuji float, když máte vektorů stovky tisíc, tak na každém bajtu paměti mi záleží a tak velkou přesnost zase nepotřebuji. Musím přetypovávat, protože se mi převodem double na float ztrácí přesnost. Já to ale přece vím a tak to taky chci, už jsem říkal, že float mi stačí.
A takových situací jsou tisíce, pak je ve výrazu víc přetypování než matematických operací. Anebo máte funkci, která jako parametry bere inty, ale vy zrovna máte všechno ostatní ve floatech. Zase musíte přetypovávat.
Nebo vydělím dvě čísla a pořád se divím, jaktože je výsledek nula? No jistě, ony to byly inty, a tím pádem bylo dělení celočíselné, přestože výsledek přiřazuji do proměnné typu Double. Ale hledejte to, kde se to stalo.
Ve VB.NET přetypováváte jenom když je to opravdu potřeba. Pokud mám komponentu poděděnou od třídy Control, tak samozřejmě přetypováváme vždy na ten typ komponenty, pokud chceme pracovat s její specifickou vlastností. Ale proč má být téměř v každém matematickém výrazu přetypovávání? A na celočíselné dělení má VB.NET speiální operátor zpětné lomítko. To je podle mě ideální řešení, nadměrné přetěžování operátorů nemám moc rád.
Neduh číslo 3 - zlaté With bloky
Takto vypadající bloky kódu mě opravdu iritují:
this.WindowContainer.formViewRectangleEditor.textBox1.Text = "ahoj";
this.WindowContainer.formViewRectangleEditor.textBox1.Width = 330;
this.WindowContainer.formViewRectangleEditor.textBox1.Height = 50;
this.WindowContainer.formViewRectangleEditor.textBox1.ForeColor = Color.SkyBlue;
Občas potřebujete nějakému zanořenému objektu nastavit víc vlastností. Takhle to vypisovat je šílené. Tak dobře, můžete udělat tohle:
TextBox textBox1 = this.WindowContainer.formViewRectangleEditor.textBox1;
textBox1.Text = "ahoj";
textBox1.Width = 330;
textBox1.Height = 50;
textBox1.ForeColor = Color.SkyBlue;
No ale to jde za předpokladu, že TextBox je třída. A co když je to strkutura? No to se pak ale moc divíte, že všechno správně nastavíte, ale když na konec ještě změny v proměnné nepřiřadíte zpátky, původní struktura zůstane nezměněná, prostě jste si jenom upravili nějakou proměnnou.
VB.NET má pro tohle speciální syntaktický konstrukt - With blok:
With Me.WindowContainer.formViewRectangleEditor.TextBox1
.Text = "ahoj"
.Width = 330
.Height = 50
.ForeColor = Color.SkyBlue
End With
Podle mě je to přehlednější a rozhodně lepší než první příklad s neustálým opisováním. A funguje i na struktury.
Možná si říkáte, že už zase vymýšlím kraviny, tak nemám struktury používat, vždyť přece máme třídy, které toho umí daleko víc. Mám k tomu ale své důvody, někdy prostě struktura stačí, nehledě na to, že jsou rychlejší. Někdy prostě struktury potřebujete. Třeba zrovna moje již zmiňovaná struktura Vector3D, tady potřebuji, abych si mohl se souřadnicemi šachovat uvnitř nějaké funkce, ale nezměnil tím vektor ve funkci, která tu vnitřní funkci zavolala.
Neduh číslo 4 - proklaté středníky
Ne, nekamenujte mě za to, není v tom nic osobního. Vyrostl jsem na BASICu, takže mi středníky prostě přijdou nelogické. Jedním z argumentů je to, že se to kompilátoru dobře parsuje. Kde je ale ta hranice? Nemáme teda začít psát v postfixu, aby to měl kompilátor ještě jednodušší?
Poznámka na okraj - postfixový zápis znamená, že nejdřív píšete parametry a pak funkci nebo operátor. Třeba 3 5 + je postfixový zápis součtu trojky a pětky, nejprve hodnoty a pak operátor. Pro kompilátor nebo interpret je to jednoduché - čte hodnoty a dává je na zásobník, když narazí na funkci, vezme si ze zásobníku tolik argumentů, kolik potřebuje, provede funkci a výsledek vrátí zase na zásobník. Výhoda je, že nepotřebujete závorky, a naimplementovat tohle je výrazně jednodušší.
Na středníky prostě nejsem zvyklý, podle mě je to zbytečný znak, když je v 99% případů za ním stejně konec řádku. V zásadě můžou nastat dva výjimečné případy - víc příkazů na jednom řádku, anebo jeden příkaz na několika řádcích. VB.NET umí oba dva případy řešit - více příkazů na jednom řádku se odděluje dvojtečkou, a jeden příkaz rozdělíte na víc řádků pomocí sekvence mezera podtržítko.
Co to ten VB vymýšlí za hlouposti a proč má tak divnou syntaxi? Je to dáno dobou jeho vzniku, jazyk BASIC byl vytvořen někdy kolem roku 1964, kdežto céčko až v roce 1972. Syntaxe většiny dnešních jazyků je odvozena od syntaxe céčka, ta je totiž velmi oblíbená. Syntaxe Visual Basicu je sice od původního BASICu hodně odlišná (řádky už opravdu nečíslujeme, jako za starých časů), ale základní myšlenky zůstaly.
Neduh číslo 5 - milion usingů na začátku
Pokud máte rozsáhlejší projekt, tak většinou prvních několik hodně řádků v C# tvoří bloky using namespace. V projektu, na kterém dělám teď, potřebuji v každé třídě nejméně 10 různých namespaců, ať už jsou to naše vlastní, nebo i ty z .NET frameworku.
Ve VB.NET můžete zaškrtnout ve Visual Studiu namespaces, které chcete používat v celém projektu, a pak je nemusíte psát na začátek každého souboru. Většinou si zaškrtnu jen ty, které potřebuji opravdu všude, a vypisouji do souborů jenom ty, které využívám jen příležitostně.
Abych jenom nechválil VB.NET
Je samozřejmě spousta věcí, které mě štvou na VB.NET. Největším problémem je to, že je strašně ukecaný. Místo toho, abyste napsali int a musíte napsat Dim a As Integer. Ve skutečnosti sice namačkám jen d a a in a Visual Studio mi zbytek doplní samo, ale to už je výhoda prostředí a upovídanost jazyka to neomlouvá.
Další věc, která mě štve, je to, že VB.NET není case sensitive. Je mimořádně pohodlné pojmenovat privátní proměnné uvnitř třídy na začátku s malým písmenem a k nim patřící veřejné property písmenem velkým. Ve VB.NET to většinou řeším podtržítkem před privátní proměnnou, což se mi ale moc nelíbí a nevypadá to hezky.
Prostředí C# má také lepší refactoring, do VB.NET musíte doinstalovat speciální nástroj třetí strany (který toho umí mírně víc), který je naštěstí zdarma, ale v základní výbavě má VB.NET jenom funkci na přejmenování.
Ale jinak si stejně pořád myslím, že VB.NET má něco do sebe a zvlášť pro začátečníky je jednodušší - neztratí se ve 4 druzích závorek a nemusí se jim vysvětlovat, proč je v tak jednoduchém výrazu pět přetypování. Díky tomu, že VB.NET i C# běží nad stejnými knihovnami, kód je víceméně identický, až na syntaktické detaily. Existuje také mnoho konvertorů.
No zkrátka mám VB.NET opravdu rád. V C# se mi programuje taky dobře, ale ve VB.NET mírně lépe. Nejlepší by ale asi byl C# bez přetypovávání, usingů a s okamžitým hlášením chyb a with bloky. Středníky mi zase až tolik nevadí a stručná céčková syntaxe není špatná. Ale i tak dnes má smysl psát ve VB.NET, je jednodušší na naučení a některé věci jsou v něm prostě lepší.