2012-01-16 13 views
7

Chciałbym wiedzieć, czy czegoś brakuje, czy nie ... Biegnę w ramach standardowej kultury Wielkiej Brytanii.Double.TryParse() ignoruje NumberFormatInfo.NumberGroupSizes?

Double result = 0; 
if (Double.TryParse("1,2,3", NumberStyles.Any, CultureInfo.CurrentCulture, out result)) 
{ 
    Console.WriteLine(result); 
} 

Oczekiwany wynik nie będzie niczym ... "1,2,3" nie powinien być analizowany jako podwójny. Jednak tak się dzieje. Według NET 2,0 MSDN documentation

AllowThousands wskazuje, że ciąg liczbowy może mieć grupy separatorów; na przykład oddzielając setki od tysięcy. Prawidłowe separatory grupy są wyznaczone przez NumberGroupSeparator i CurrencyGroupSeparator właściwości NumberFormatInfo i liczbę cyfr w każdej grupie jest określana przez NumberGroupSizes i CurrencyGroupSizes właściwości NumberFormatInfo.

Pozwolić na tysiące jest wliczony w NumberStyles.Any. NumberGroupSizes to 3 dla mojej kultury. Czy to tylko błąd w Double.Parse? wydaje się mało prawdopodobne, ale nie mogę zauważyć, co robię źle ...

+0

To może być dlatego mam ważny rezultat podczas testowania [moja odpowiedź] (http://stackoverflow.com/questions/1014535/float-parse-doesnt-work-the -way-i-wanted/1014559 # 1014559) na podobne pytanie. – ChrisF

+0

Po prostu ciekawa, ale jaka jest wartość wyniku? – Aaron

+0

Myślę, że musiałbyś zapytać Microsoft, jeśli jest to błąd, ale dostaję takie samo zachowanie jak ty. Zawsze można zrobić "NumberStyles.Any^NumberStyles.AllowThousands", ale nie jest to zbyt użyteczne, jeśli spodziewasz się uzasadnionych grup składających się z trzech osób. – Jodrell

Odpowiedz

5

To po prostu oznacza, że ​​ciąg wejściowy może zawierać zero lub więcej instancji NumberFormatInfo.NumberGroupSeparator. Ten separator może służyć do oddzielania grup liczb o dowolnym rozmiarze; nie tylko tysiące. NumberFormatInfo.NumberGroupSeparator i NumberFormatInfo.NumberGroupSizes są używane podczas formatowania dziesiętnych jako ciągów. Używając Reflectora wydaje się, że NumberGroupSeparator służy tylko do określenia, czy znak jest separatorem, a jeśli jest, jest pomijany. NumberGroupSizes nie jest w ogóle używany.

Jeśli chcesz sprawdzić poprawność łańcucha znaków, możesz to zrobić za pomocą polecenia RegEx lub napisać metodę, aby to zrobić. Oto jeden właśnie włamał się razem:

string number = "102,000,000.80"; 
var parts = number.Split(','); 
for (int i = 0; i < parts.Length; i++) 
{ 
    var len = parts[i].Length; 
    if ((len != 3) && (i == parts.Length - 1) && (parts[i].IndexOf('.') != 3)) 
    { 
     Console.WriteLine("error"); 
    } 
    else 
    { 
     Console.WriteLine(parts[i]); 
    } 
} 

// Respecting Culture 
static Boolean CheckThousands(String value) 
{ 
    String[] parts = value.Split(new string[] { CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator }, StringSplitOptions.None); 
    foreach (String part in parts) 
    { 
     int length = part.Length; 
     if (CultureInfo.CurrentCulture.NumberFormat.NumberGroupSizes.Contains(length) == false) 
     { 
      return false; 
     } 
    } 

    return true; 
} 
+0

+1, wydaje się, że 'NumberGroupSizes' jest zignorowany podczas parsowania (wewnętrzną metodą jest' Number.ParseNumber'). – user7116

+0

Właśnie zacząłem kopać z Reflectorem, ale nie miałem czasu, aby zająć tak daleko. Zastanawiam się nad użyciem Regexu, ale muszę być ostrożny i upewnić się, że wszystko nadal jest świadome. – Ian

+0

@Ian Możesz budować wyrażenia Regex na podstawie informacji przechowywanych w NumberFormatInfo dla każdej kultury. –