Avatar
Nikola Sterziková (PaNika):

Ahoj,
mám MVC aplikaci. Při postbacku mi v modelu přijde hodnota string, kterou potřebuji ohodnotit, že je číslo (respektive int).
Kód v C# je jednoduchý :

 int i;
 if(!int.TryParse(s, out i))
{ // něco
}

Hodnota s je např.: "0" (celé číslo v textové podobě).

Pokud aplikaci spouštím v Chrome (či Opeře, Firefoxu), vše funguje, pokud ji spustím v Edge nebo v IE, string je vyhodnocen jako neplatný formát.
Už jsem vyzkoušela nastavování CultureInfo:

 CultureInfo culture = new CultureInfo("cs-CZ");
var nfi = (NumberFormatInfo)culture.GetFormat(typeof(NumberFormatInfo));
if(!int.TryParse(s,NumberStyles.Integer, nfi, out i))
{ // něco
}

a také invariantCulture a stále stejné.
Tuším, že by problém mohl být v kódování, ale nevím jak na to...
Věděl byste někdo?
Dík za pomoc..

 
Odpovědět 22. září 16:58
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

dej si breakpoint a zjistis, co je v tom stringu. nebo si to dej vypsat.. beztah to bude prazdny string,nebo neco podobneho.

 
Nahoru Odpovědět 22. září 22:08
Avatar
Odpovídá na Marian Benčat
Nikola Sterziková (PaNika):

Nene, nejsem úplně blbá, ladit umím.
Přijde tam stejná hodnota jako z Chrome. Například "0" nebo "1" a stejně to spadne...
Právě proto mě to tak strašně udivilo, až jsem se musela někde zeptat...

Editováno 23. září 9:06
 
Nahoru Odpovědět 23. září 9:05
Avatar
Nikola Sterziková (PaNika):

Přikládám PrintScereen...

 
Nahoru Odpovědět 23. září 9:14
Avatar
HONZ4
Člen
Avatar
HONZ4:

nevím sice jak ten problém řešit, ale zkusil bych si udělat pro zajímavost malý test (omlouvám se, jestli tě to už napadlo). Zajímalo by mě co jak dopadne vyhodnocení:

int i = 0;
if(0==s.CompareTo(i.ToString()) // jen musíš zajistit, aby to předávalo "0" jako v to náhledu
{
 // pokud se to dostane sem, tak to asi kódováním nebude
}
if(!int.TryParse(s, out i))
{ // něco
}
Editováno 23. září 19:02
 
Nahoru Odpovědět 23. září 19:01
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

lol.. to jsem jeste nevidel :-) Koukni se do tech postbacku prosim na hlavicky..

 
Nahoru Odpovědět 23. září 19:03
Avatar
Odpovídá na Nikola Sterziková (PaNika)
Luboš Běhounek (Satik):

Není v tom stringu nějaký netisknutelný znak, třeba konec řádku nebo tak něco, který se ti v debuggeru neukáže? Kolik je délka toho stringu, je to opravdu 1? :)

Případně ještě zkus před prasováním zavolat na tom stringu .Trim()

Editováno 23. září 19:10
Nahoru Odpovědět 23. září 19:09
:)
Avatar
Martin Dráb
Redaktor
Avatar
Odpovídá na Nikola Sterziková (PaNika)
Martin Dráb:

Zkoušela jsi něco na tento způsob?

s = "0";
int i;
 if(!int.TryParse(s, out i))
{ // něco
}

Problém by taky mohl nastat, kdyby v tom řetězci byla hodnota, která spadá do rozsahu bezznaménkového integeru, ale ne do znaménkového (např. 0x80001000, popř. dekadický ekvivalent).

Tady to vypadá, že někde máš špatně nějakou drobnost (čím déle ji hledáš, tím je ta drobnost menší). Někdy pomůže to nechat pár dní být a nechat pracovat podvědomí.

Nahoru Odpovědět 23. září 19:53
2 + 2 = 5 for extremely large values of 2
Avatar
Nikola Sterziková (PaNika):

Tak jsem na to přišla, ale pořád tomu nerozumím.
Je to něco podobného, co píšete.

Z toho stringu, co mi chodí z prohlížeče jsem si udělala charArray, a co nevidím, toto pole je jiné pokud data posílá Chrome a pokud je posílá IE/Edge.
IE/Edge do toho pole přidává znaky uvozovek, které se však při ladění vůbec neukazují, takže při vyhodnocování nakonec string není číslo (nebo v mém případě potřebuju ohodnotit na datetime).
Snad je to vidět na přiložených obrázcích.
Vstupní string byl: 0:00:10 pro IE a 0:00:12 pro Chrome.

Takže jsem to musela vyřešit takovým hackem:

public static string IEHackforTime(string time)
        {
            string newTime = "";
            var arr = time.ToCharArray();
            foreach( var c in arr)
            {
                if (Char.IsNumber(c) || c==':' )
                {
                    newTime += c.ToString(); // Pole má 12 znaků, StringBuilder v tomto případě nemá smysl
                }
            }
            return newTime;
        }
 
Nahoru Odpovědět  +1 26. září 10:56
Avatar
Odpovídá na Nikola Sterziková (PaNika)
Luboš Běhounek (Satik):

Zrovna tady bych ten Stringbuilder použil, jinak tě GC nebude mít rád, protože mu při každém průchodu vytvoříš spoustu nových objektů navíc (string je immutable, takže každé připojení písmenka vytváří novou instanci stringu) :)

Editováno 26. září 11:11
Nahoru Odpovědět 26. září 11:10
:)
Avatar
Odpovídá na Luboš Běhounek (Satik)
Nikola Sterziková (PaNika):

jj, já vím. Tady zrovna by mělo ve výsledku být jen 7 stringů, 6 z toho zbytečných, nezdálo se mi, že to GC mělo tak zatížit, no, ale app by se měly psát správně to jooo :-D

 
Nahoru Odpovědět 26. září 12:00
Avatar
Odpovídá na Nikola Sterziková (PaNika)
Luboš Běhounek (Satik):

To uz pak zalezi na tom, jestli to bude volany treba jednou za den nebo 100x za minutu :)

Nahoru Odpovědět 26. září 12:02
:)
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

Jojo, string builder je hodně chytrý.. kromě toho že to drží vnitřně v poli, tak těch polí má několik rozděleneých po určité velikosti (tuším že aktuálně je ta mez 84kb) tak aby se to nepresunulo do huge object poolu, kde je to vše o řád pomalejší ;-)

 
Nahoru Odpovědět 26. září 12:02
Avatar
Odpovídá na Luboš Běhounek (Satik)
Nikola Sterziková (PaNika):

no právě, že to bude volané tak 20x za den v období 2 týdnů a pak půl roku ne... :-D

 
Nahoru Odpovědět 26. září 12:10
Avatar
coells
Redaktor
Avatar
Odpovídá na Luboš Běhounek (Satik)
coells:

Ohledně StringBuilderu je to trochu mýtus a od .NET 2.0 to už neplatí.
StringBuilder také vytváří spoustu nových objektů, rozdíl je v něčem jiném.

Když používáš StringBuilder, občas se nový objekt nevytvoří, protože máš pre-allocated pole.
To ovšem nemůžeš dělat moc často, jinak bys dospěl ke kvadratickému poměru stejně jako String, vysvětlím.

Hlavní trik je v tom, že StringBuilder vytváří nové objekty v lineárním poměru vůči vstupu, to znamená, že 1000 volání Append() alokuje ~1000/K polí a dalších objektů o celkové velikosti ~1000*L, kde K a L jsou nějaké velice malé konstanty.

String při 1000 volání concat alokuje 1000 polí o celkové velikosti ~10002, což je kvadratický poměr a tady je zádrhel a důvod, proč je SB občas lepší.

Obecná rada je nechytit se do premature optimalizací, takže nepoužívat StringBuilder jen tak.

Rule of thumb:

  1. použít StringBuilder, když chceš využít jeho přetížené Append() metody v komplexnějším kódu, ty jsou super
  2. použít StringBuilder, když ti profiler ukáže, že je tam problém - a překvapivě většinou ukáže někam úplně jinam

V opačném případě si nekomplikuj život, hezčí kód vyhrává.

 
Nahoru Odpovědět  +3 26. září 14:18
Avatar
Odpovídá na coells
Luboš Běhounek (Satik):

Měl jsem za to, že když vytvoříš instanci SB s parametrem třeba 1000, tak vytvoří buffer o velikosti 1000 znaků a rovnou to do něj všechny znaky zapisuje, takže se nevytváří žádné další instance stringů navíc, teď jsi mě trochu zmátl :D

EDIT: Beru zpět to zmatení, blbě jsem to pochopil napoprvé :)

Editováno 26. září 14:29
Nahoru Odpovědět 26. září 14:27
:)
Avatar
hanpari
Redaktor
Avatar
Odpovídá na Nikola Sterziková (PaNika)
hanpari:

Není problém ve znakové sadě? Když jsem se s něčím takovým setkal, předpokládal jsem utf-8, což nebyla pravda.

 
Nahoru Odpovědět 26. září 14:33
Avatar
coells
Redaktor
Avatar
Odpovídá na Luboš Běhounek (Satik)
coells:

To máš pravdu, jedná se o tu konstantu K, kterou uvádím, a kterou je hrozně těžké specifikovat obecně, defaultně by měla být 16.

Pokud bys použil StringBuilder(1000) a dal tam 10 znaků, máš 990 znaků overhead (a drobné kvůli alignmentu v paměti), pokud bys tam dal 1010 znaků, máš 990 znaků overhead. Když takovou metodu budeš volat velice často, prakticky se nedá odhadnout, jestli je lepší StringBuilder(16) nebo StringBuilder(1024)?

Profiler většinou ukazuje na přesný opak toho, co bys jako programátor předpokládal, používal jsem ho, když jsem opravdu musel a do jednoho případu mě vždy vyvedl z omylu, proto je lepší napsat hezčí kód (ať už to znamená cokoliv) a neřešit rychlost nebo paměť.

 
Nahoru Odpovědět  +2 26. září 14:42
Avatar
coells
Redaktor
Avatar
Odpovídá na Nikola Sterziková (PaNika)
coells:

Podle toho tvého obrázku to nejsou uvozovky, ale LRM znak https://en.wikipedia.org/…o-right_mark
Skoro to vypadá, jako na nějaký speciální control, který v IE neodstraňuje formátování a pošle ti to na server celé.

 
Nahoru Odpovědět 26. září 14:58
Avatar
coells
Redaktor
Avatar
Odpovídá na Nikola Sterziková (PaNika)
coells:

Tak podle všeho IE/Edge v metodě Date.toLocaleString() a jí podobných vkládá tyhle kódy, aby při internacionalizaci (např. do arabštiny) byl text flow korektní. Ať už ji voláš kdekoliv, počítej s tím, že UI Locale by se na server nemělo dostávat.

Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
 
Nahoru Odpovědět  +1 26. září 15:08
Avatar
Odpovídá na coells
Nikola Sterziková (PaNika):

To vypadá, že je to ono. :-) V javascriptu opravdu volám .toLocaleTimeS­tring, protože hodnotu potřebuji zároveň i zobrazit a pak teprve volám Ajaxem metodu controleru.
Ale moc nerozumím tvé poslední větě:

Ať už ji voláš kdekoliv, počítej s tím, že UI Locale by se na server nemělo dostávat.

Jako, že nemám v JS volat .toLocaleTimeS­tring?

 
Nahoru Odpovědět 26. září 15:58
Avatar
coells
Redaktor
Avatar
Odpovídá na Nikola Sterziková (PaNika)
coells:

Volat toLocaleString bys na klientovi určitě měla :-) ale tuhle hodnotu jenom zobrazuj a neposílej na server.
Některá prostředí ti dokonce ani nemusí vrátit arabské číslice, to záleží jen na nastavení locale klienta.

Na server musíš posílat něco invariantního.
V naší aplikaci (nikoliv MVC) používáme ISO normu normalizovanou na UTC (toISOString) nebo POSIX normu (getTime), ale záleží na tom, jaké knihovny podporuješ a s čím se ti bude lépe pracovat, ISO je jistota.

 
Nahoru Odpovědět  +1 26. září 16:52
Avatar
Odpovídá na coells
Nikola Sterziková (PaNika):

No, ona to je malinkatá aplikace o 3 stránkách a potřebuju tam měřit čas, jak něco dlouho trvalo a pak ukládat do db. Právě jedena komplikace je volání metody GET s parametrem času. Přišlo mi nejjednodušší vyrobit z času string, nahradit dvojtečky za podtržítka a na serveru parsovat zpět. UTC je (v letním čase) o 2 hodiny jinak, na to by se pak taky nesmělo zapomenout... a počítat počet milisekund od půlnoci 1970 se mi moc nechtělo (getTime)... I když je fakt, že počet milisekund by se v URL parametru posílal nejlépe a odpadlo by i složité ruční ohodnocování, zda posílaný parametr je opravdu číslo, zařídil by to Attribut routing, to je fakt...

 
Nahoru Odpovědět 27. září 9:44
Avatar
coells
Redaktor
Avatar
Odpovídá na Nikola Sterziková (PaNika)
coells:

Jestli měříš čas a milisekundy jsou dostačující, tak je integer dost dobrá volba.

Také měříme a ukládáme čas, ale držíme ho v sekundách jako float kvůli kompatibilitě s POSIX normou, jediný JS má totiž milisekundy jako časovou jednotku, všechny ostatní knihovny jedou na sekundy a všechny knihovny epochy podporují.
V databázi se s tím pak snadno pracuje, ať už děláš agregovaný SQL dotaz nebo map-reduce.

Ohledně UTC - datum je časový okamžik, který může mít různé reprezentace, UTC není o 2 hodiny zpět proti SEC, je to stejný časový okamžik v jiném formátu, podobně jako můžeš napsat 23 == 0x17, pořád máš stejnou hodnotu. Na server a do databáze je nejlepší normalizovat právě z toho důvodu, abys mohla ignorovat zónu a vždy pracovala se stejnou hodnotou. Když to nedodržíš, začnou se dít ošklivé věci, lidé mají datum narození o den zpět, události se dějí v budoucnosti, atd. Na klientovi naopak vždy víš, že čas je UTC a můžeš ho převádět do zóny uživatele, což u amerických zón dělá dost velký rozdíl.

 
Nahoru Odpovědět 27. září 12:18
Avatar
Odpovídá na coells
Nikola Sterziková (PaNika):

Přesnost je pro mě bohatě dostačující na sekundy.
Měla to být jednoduchá app, napsaná za 1-2 odpoledne, běžící pouze na intranetu, žádné databázové složitosti, prostý CRUD promocí EF. Na klientu maximálně jQuery...
Ale budu vědět pro příště :-)
Díky moc za pomoc.

 
Nahoru Odpovědět  +1 27. září 15:25
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 25 zpráv z 25.