Diskuze: If, else a switch
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Neregistrovaný

Zobrazeno 28 zpráv z 28.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Coo - pokud je bolean vyhodnocen v if jako true, provede se if část, jinak else. Jestli else potřebuješ je přeci na tobě... else se už vůbec nehodnotí - je to prostě zbytek...
else tam dávat vůbec nemusíš být tebou tak to udělám do switche, tohle je zrůdovina.
switch(vobla)
{
case 1: vysledek = a + b;
break;
case 2: vysledek = a - b;
break;
// a tak dále..
}
V tomhle případě rozdíl mezi použitím a nepoužitím else je ten, že s else je to rychlejší.
Celá else větev se vůbec neprovádí, pokud byla podmínka splněna.
Tvůj kód s else (zapsaný trochu přehledněji, aby to bylo lépe vidět):
if (volba == 1)
vysledek = a + b;
else
if (volba == 2)
vysledek = a - b;
else
if (volba == 3)
vysledek = a * b;
else
if (volba == 4)
vysledek = a / b;
Ale jak psal Зайчик , na tohle je lepší switch, který kompilátor dokáže efektivně zoptimalizovat.
Já bych to udělal takto:
Action<int, int>[] operations = new Action<int, int>[]
{
delegate (int a, int b) { vysledek = a + b; },
delegate (int a, int b) { vysledek = a - b; },
delegate (int a, int b) { vysledek = a * b; },
delegate (int a, int b) { vysledek = a / b; }
};
...
Action[volba](a, b);
Ani ne... (Nemám čas -
spěchám...)
Místo:
Action[volba](a, b);
Má být samozřejmě:
operations[volba](a, b);
nevím proč by to mělo být špatně, ale je snad jasný že nejednodušší způsob je ten nejlepší a v tomhle případě to bude ten můj si myslím
Až budu potřeboval bagrem vyhrabat díru pro zasazení petrželky, tak se
ti ozvu, jo?
Samozřejmě že Winitrixův způsob je správně, zvlášť jako rada začátečníkovi. Pokud si někdo chce zafrajeřit a použít místo normálního switche seznam odkazů na funkci, měl by aspoň vědět, jak se to píše.
Matesi, až budou ty tvoje paskvily aspoň fungovat, co kdybys zkusil napsat nějakej obfuscator? Ty jseš na to jak zrozenej!
A místo Action<,> má být samozřejmě Func<,,> a samozřejmě je to celý uplně zbytečný.
Kdepak - jede mi to... (A
může tam být obojí.)
Sorry, že nevětvím ihned, jakmile mne jiného nic nenapadne. switch je obecně hrozný... (a přehlednost to zase tak moc nepřebíjí)
Hm. Teď možná jo. Protože jsi to zeditoval. Původně tam bylo tohle:
Action<int, int>[] operations = new Action<int, int>[]
{
delegate (int a, int b) { a + b },
delegate (int a, int b) { a - b },
delegate (int a, int b) { a * b },
delegate (int a, int b) { a / b }
};
PROČ je zase switch obecně hrozný? Nefunguje? Je míň přehledný než ten tvůj seznam delegátů, který jsi ani nedokázal napoprvé napsat správně? Je někomu, kdo jde číst článek o větvení, k něčemu příklad na vyhnutí se větvení? Když tak nerad větvíš, tohle není tvůj kód?
function MapMenu(ul) {
if (!ul.hasChildNodes())
return;
for (var index in ul.childNodes) {
if (!ul.childNodes[index].tagName)
continue;
if (ul.childNodes[index].tagName.toLowerCase() == 'li') {
if (ul.childNodes[index].hasChildNodes())
for (var c in ul.childNodes[index].childNodes) {
if (!ul.childNodes[index].childNodes[c].tagName)
continue;
if (ul.childNodes[index].childNodes[c].tagName.toLowerCase() == 'ul') {
$(ul.childNodes[index]).hover(function () {
OpenSubMenu(this);
}, function () {
HideMenu();
});
MapMenu(ul.childNodes[index].childNodes[c]);
}
}
}
}
}
Hmm - to s tím hodně souvisí... Kde vidíš switch? Přečti si o něm něco...
Složitější switche mohou být opravdu na obtíž a dají se nahradit lepšími konstrukcemi, nicméně v aktuálním případě je switch naprosto v pořádku. Nevím, proč musí matesax stále radit své hashmapy a delegáty někomu kdo má za sebou prvních 5 lekcí jazyka. Matěji, to ti opravdu nedojde, že u 5. lekce kde se vysvětluje jak funguje IF, není vhodné vytahovat delegáty? Jsem z tvého chování na devbooku již velmi unaven, řešili jsme to spolu již několikrát a je to stále dokola. Pokud chceš na devbooku dále působit, naposledy tě prosím, abys přestal psát začátečníkům nesmysly. Děkuji.
Co je na switchi hroznýho? Pokud jde použít, tak je mnohem přehlednější než if else větvení. Odkazy na funkce/metody bych použil pokud by to větvení bylo zbytečně dlouhý a ty větve byly delší. Tady jsou 4 větve a každá na jeden řádek, to je trochu kanon na vrabce.
Složitější switche mohou být na obtíž?
A jak bys tedy třeba jinak (přehledněji) napsal switch pro třeba 150 hodnot?
Nesprávné použití switche je třeba toto:
switch (hodnota)
{
case 1:
return "jedna";
break;
case 2:
return "dva";
break;
...
}
Toto v různých formách opravdu často vídám, lepší řešení je toto:
string[] hodnoty = {"jedna", "dva", ...};
return hodnoty[hodnota - 1];
Switch můžeme nahradit dále zmíněnými delegáty. Pokud v programu evidujeme 100 vzorců, je určitě dobrý nápad to tak udělat, viz. ta Matějova příšernost, která se v dané situace ale vůbec nehodí.
Pokud mámě někde 500ti řádkový switch, je vhodné kód jednotlivých větví rozdělit do metod, vznikne pak toto:
switch (hodnota)
{
case 1:
jedna();
break;
case 2:
dva();
break;
...
}
Pokud se i toto zvrhne, je lepší použít předávání tříd, vypůjčím si ukázku ze Stack Overflow (http://stackoverflow.com/…ents-bad-oop)
switch (eFoo)
{
case Foo.This:
eatThis();
break;
case Foo.That:
eatThat();
break;
}
switch (eFoo)
{
case Foo.This:
drinkThis();
break;
case Foo.That:
drinkThat();
break;
}
Refaktorujeme na:
IAbstract
{
void eat();
void drink();
}
class This : IAbstract
{
void eat() { ... }
void drink() { ... }
}
class That : IAbstract
{
void eat() { ... }
void drink() { ... }
}
Abychom si rozuměli, neříkám, že je switch špatný. Do určité úrovně je naprosto v pořádku, ale jakmile se nám to moc rozleze, měli bychom zvážit refaktorování kódu na něco vhodnějšího. Tak je to přeci s každou programátorskou konstrukcí.
Co jsi tu ukázal moc nesouvisí se složitostí switche, ale s použitím switche ve špatné situaci.
Pokud máš switch, který zpracovává třeba nějakou multiplayerovou herní logiku (kde těch hodnot může být třeba 500 a každá se zpracovává nějak odlišně), tak je pořád switch nejvhodnější, i když je rozlezlý (samozřejmě je vhodné nevykonávat kód přímo v tom switchi, ale volat z něj jednotlivé metody, to jsi tam zmiňoval).
Mám za to, že jednoduchý switch nevadí nikdy. Až se zvyšující se složitostí má smysl vymýšlet co s tím, tedy lidově řečeno "až v tom začne být bordel".
Co konkrétně máš v jednotlivých casech v tom switchi ze hry?
V té strategii, co teď dělám, žádný velký switch nemám, ale v předchozím působišti jsme měli switch, kde bylo asi 170 case v největším switchi, tady je ukázka nějakého už většího switche (ale jsou tam i mnohem větší, ale vypadají podobně):
Složitější věci mají vlastní funkci, jednoduché na pár řádků se tady řeší přímo ve switchi.
Tohle se obecně řeší přes rozhraní, uděláš si interface IEvent s metodou Execute() a pak třídu pro každou událost, switch pak není potřeba, na eventu co přijde rovnou zavoláš Execute a je ti jedno jakého je typu.
Vždycky to ale tak nejde, záleží na tom, odkud ti ty eventy lezou, předpokládám, pokud jsou to třeba stringy ze sítě, tak to bez switche asi nepůjde. Tento případ jsem viděl řešit přes slovník, kde byl klíč string a hodnota delegát, takový slovník eventů byl velmi přehledný. Delegátu se dá vyhnout tak, že předáme instanci co implementuje rozhraní IEvent. Viděl jsem to řešit také přes reflexi, kde měla obslužná metoda ten samý název jako událost, to ale asi trochu degraduje výkon.
Nojo, to mi nedošlo a atributy to v C# ještě celé zjednoduší
Uh, s těma delegátama by to bylo složitější, protože některé funkce parametrů mají víc a některé nemají třeba žádný.
Šlo by to samozřejmě třeba obejít tím, že by se všude posílal jako parametr typ Object a ten se ignoroval (pokud žádný parametr není) nebo v případě více parametrů by v něm bylo uloženo pole objektů, ale než vymýšlet tyhle kontrukce, tak radši použiju switch, i pro nově příchozího člověka ten kód se switchem bude mnohem přehlednější...
Přeci nebudeme vynalézat kolo, patternů co řeší parametry událostí je mnoho, sám C# předává potomky EventArguments. Uplně nejjednodušeji tam můžeš dát pole Objectů. Nebo použít zmíněnou reflexi.
Myslím že pro nově příchozího člověka ten kód co jsi poslal moc
přehledný nebude
Zobrazeno 28 zpráv z 28.