IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
BeriCud
Neregistrovaný
Avatar
BeriCud:10.2.2013 18:23

Ahoj už jsem se jednou na jednu věc ptal a moc děkuji za vysvětlení a Vaši pomoc. Mám ještě jednu otázku v předposledním programu nazvaném kalkulačka se používá if a else. Rozumím jak to funguje jen nechápu výhodu tohoto zápisu. Myslím konkrétně tady toto:
Console.Write­Line("Zvolte si operaci:");
Console.Write­Line("1 - sčítání");
Console.Write­Line("2 - odčítání");
Console.Write­Line("3 - násobení");
Console.Write­Line("4 - dělení");
int volba = int.Parse(Con­sole.ReadLine());
float vysledek = 0;
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;
Jdeš mi o to zvýrazněné else jakou to má výhodu je tam dávat když program funguje stejně i bez nich a ikdyž tam jsou musí se zjistit jestli náhodou je podmínka splněna tak že if tam musí a else bych moch vynechat a kod by se zkrátil.

 
Odpovědět
10.2.2013 18:23
Avatar
matesax
Tvůrce
Avatar
Odpovídá na
matesax:10.2.2013 18:35

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...

 
Nahoru Odpovědět
10.2.2013 18:35
Avatar
Зайчик
Člen
Avatar
Odpovídá na
Зайчик:10.2.2013 18:48

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..
}
Nahoru Odpovědět
10.2.2013 18:48
Коммунизм для нашего будущего!
Avatar
Odpovídá na
Luboš Běhounek Satik:10.2.2013 19:35

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.

Editováno 10.2.2013 19:36
Nahoru Odpovědět
10.2.2013 19:35
https://www.facebook.com/peasantsandcastles/
Avatar
matesax
Tvůrce
Avatar
Odpovídá na Зайчик
matesax:10.2.2013 19:37

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);
Editováno 10.2.2013 19:40
 
Nahoru Odpovědět
10.2.2013 19:37
Avatar
lcet.m
Člen
Avatar
Odpovídá na matesax
lcet.m:10.2.2013 19:40

To bys to udělal blbě, no.

 
Nahoru Odpovědět
10.2.2013 19:40
Avatar
matesax
Tvůrce
Avatar
Odpovídá na lcet.m
matesax:10.2.2013 19:41

Ani ne... :) (Nemám čas - spěchám...)

Místo:

Action[volba](a, b);

Má být samozřejmě:

operations[volba](a, b);
Editováno 10.2.2013 19:42
 
Nahoru Odpovědět
10.2.2013 19:41
Avatar
Зайчик
Člen
Avatar
Odpovídá na matesax
Зайчик:10.2.2013 19:43

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

Nahoru Odpovědět
10.2.2013 19:43
Коммунизм для нашего будущего!
Avatar
Odpovídá na matesax
Luboš Běhounek Satik:10.2.2013 19:48

Až budu potřeboval bagrem vyhrabat díru pro zasazení petrželky, tak se ti ozvu, jo? :)

Nahoru Odpovědět
10.2.2013 19:48
https://www.facebook.com/peasantsandcastles/
Avatar
lcet.m
Člen
Avatar
lcet.m:10.2.2013 19:50

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!

 
Nahoru Odpovědět
10.2.2013 19:50
Avatar
lcet.m
Člen
Avatar
Odpovídá na matesax
lcet.m:10.2.2013 19:52

A místo Action<,> má být samozřejmě Func<,,> a samozřejmě je to celý uplně zbytečný.

 
Nahoru Odpovědět
10.2.2013 19:52
Avatar
matesax
Tvůrce
Avatar
Odpovídá na lcet.m
matesax:10.2.2013 20:06

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í)

 
Nahoru Odpovědět
10.2.2013 20:06
Avatar
lcet.m
Člen
Avatar
Odpovídá na matesax
lcet.m:11.2.2013 8:59

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 }
};
 
Nahoru Odpovědět
11.2.2013 8:59
Avatar
lcet.m
Člen
Avatar
Odpovídá na matesax
lcet.m:11.2.2013 9:09

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]);
                    }
                }
        }
    }
}
 
Nahoru Odpovědět
11.2.2013 9:09
Avatar
matesax
Tvůrce
Avatar
Odpovídá na lcet.m
matesax:11.2.2013 9:23

Hmm - to s tím hodně souvisí... Kde vidíš switch? Přečti si o něm něco...

 
Nahoru Odpovědět
11.2.2013 9:23
Avatar
lcet.m
Člen
Avatar
Odpovídá na lcet.m
lcet.m:11.2.2013 9:27

"switch je obecně hrozný" jsi napsal ty. Já se ptám proč.

 
Nahoru Odpovědět
11.2.2013 9:27
Avatar
David Hartinger
Vlastník
Avatar
David Hartinger:11.2.2013 9:45

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.

Editováno 11.2.2013 9:46
Nahoru Odpovědět
11.2.2013 9:45
New kid back on the block with a R.I.P
Avatar
Lukáš Hruda
Tvůrce
Avatar
Odpovídá na matesax
Lukáš Hruda:11.2.2013 9:46

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.

 
Nahoru Odpovědět
11.2.2013 9:46
Avatar
Odpovídá na David Hartinger
Luboš Běhounek Satik:11.2.2013 9:51

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?

Nahoru Odpovědět
11.2.2013 9:51
https://www.facebook.com/peasantsandcastles/
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Luboš Běhounek Satik
David Hartinger:11.2.2013 10:02

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í.

Editováno 11.2.2013 10:02
Nahoru Odpovědět
11.2.2013 10:02
New kid back on the block with a R.I.P
Avatar
Odpovídá na David Hartinger
Luboš Běhounek Satik:11.2.2013 10:19

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).

Nahoru Odpovědět
11.2.2013 10:19
https://www.facebook.com/peasantsandcastles/
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Luboš Běhounek Satik
David Hartinger:11.2.2013 10:24

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?

Nahoru Odpovědět
11.2.2013 10:24
New kid back on the block with a R.I.P
Avatar
Odpovídá na David Hartinger
Luboš Běhounek Satik:11.2.2013 10:41

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ě):

http://pastebin.com/isQVnUT6

Složitější věci mají vlastní funkci, jednoduché na pár řádků se tady řeší přímo ve switchi.

Nahoru Odpovědět
11.2.2013 10:41
https://www.facebook.com/peasantsandcastles/
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Luboš Běhounek Satik
David Hartinger:11.2.2013 10:50

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.

Editováno 11.2.2013 10:53
Nahoru Odpovědět
11.2.2013 10:50
New kid back on the block with a R.I.P
Avatar
lcet.m
Člen
Avatar
lcet.m:11.2.2013 11:32

Na něco podobného jsem tu reflexi použil, obsluhující metody musí být označeny atributem, podle kterého se přiřadí metoda k signálu. Výkon je ok, protože se na začátku naplní Dictionary<string, MethodInfo>

 
Nahoru Odpovědět
11.2.2013 11:32
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na lcet.m
David Hartinger:11.2.2013 11:34

Nojo, to mi nedošlo a atributy to v C# ještě celé zjednoduší :)

Nahoru Odpovědět
11.2.2013 11:34
New kid back on the block with a R.I.P
Avatar
Odpovídá na David Hartinger
Luboš Běhounek Satik:11.2.2013 11:42

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ší...

Nahoru Odpovědět
11.2.2013 11:42
https://www.facebook.com/peasantsandcastles/
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Luboš Běhounek Satik
David Hartinger:11.2.2013 11:53

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 :)

Nahoru Odpovědět
11.2.2013 11:53
New kid back on the block with a R.I.P
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 28 zpráv z 28.