2011-01-13 33 views
7

câu hỏi ngắn:C# decimal.Parse hành vi

Tại sao những '.....' có giá trị trong phân tích một số thập phân trong .NET (C#):

decimal res = decimal.Parse("8......15"); // returns 815 
decimal res = decimal.Parse("8...15");  // returns 815 
decimal res = decimal.Parse("8..15");  // returns 815 

lý do là gì điều này?

+0

Tôi đã kiểm tra nó trong .NET4.0. Nó đưa ra một ngoại lệ định dạng – HuBeZa

+0

Bạn đang sử dụng văn hóa nào? Không thể phân tích cú pháp các chuỗi đó bằng văn hóa hiện tại của tôi hoặc văn hóa bất biến. – LukeH

+0

Tôi nghĩ đó là một sự lười biếng lập trình viên. Tôi đã không nhìn thấy một nơi sử dụng hàng nghìn dấu phân cách lỏng lẻo. – HuBeZa

Trả lời

18

Nó không thành công cho tôi. Bạn có cơ hội nào trong một nền văn hóa nơi "." là dấu tách hàng nghìn và "," là dấu thập phân? Decimal.Parse (và các cuộc gọi tương tự) sử dụng văn bản hiện tại của chuỗi theo mặc định. Cho dù đó là một điều tốt hay không thì còn phải bàn, nhưng không liên quan đến hành vi thực tế :)

Cố gắng xác định CultureInfo.InvariantCulture trong decimal.Parse gọi:

decimal res = decimal.Parse("8......15", CultureInfo.InvariantCulture); 

Tôi tin rằng sẽ cư xử như bạn mong đợi.

+0

Tôi nghĩ bạn đã đánh vào đầu trên đó. Nó phân tích chính xác nếu bạn sử dụng văn bản 'de-DE', ví dụ. – LukeH

+0

'es-ES' đến. Thật là một nền văn hóa kỳ lạ – HuBeZa

+0

Thật vậy. My CurrentCulture là "nl-BE", NumberDecimalSeparator = "," và NumberGroupSeparator = "." Cảm ơn! Nhưng nó là khá lạ mà họ cho phép ký hiệu như vậy. – juFo

1

Tôi không biết tại sao, nhưng tôi biết cách hoạt động (phần mã phân tích cú pháp thập phân xem bên dưới). Tôi nghĩ cuối cùng nếu chỉ cần bật cờ điểm và bỏ qua tất cả các điểm.

while (true) 
{ 
    if (((ch >= '0') && (ch <= '9')) || (((options & NumberStyles.AllowHexSpecifier) != NumberStyles.None) && (((ch >= 'a') && (ch <= 'f')) || ((ch >= 'A') && (ch <= 'F'))))) 
    { 
     //Here goes some code... 
    } 
    else if ((((options & NumberStyles.AllowDecimalPoint) != NumberStyles.None) && ((num & 0x10) == 0)) 
    && (((chPtr2 = MatchChars(p, currencyDecimalSeparator)) != null) || ((flag && ((num & 0x20) == 0)) 
    && ((chPtr2 = MatchChars(p, numberDecimalSeparator)) != null)))) 
    { 
     num |= 0x10; 
     p = chPtr2 - 1; 
    } 
} 

Sử dụng công cụ Reflector để điều tra tất cả mã.

+0

Thú vị! Rất vui khi thấy mã phần về HexSpecifier. – juFo

2

Tôi cho rằng đó là do trình phân tích cú pháp không thực sự quan tâm đến các trình tách nhóm - chúng không liên quan đến quá trình chuyển đổi chuỗi thành số thập phân.

Chúng tôi gọi chúng là dấu phân cách hàng nghìn, nhưng chúng thực sự không. Chúng là các nhóm phân tách nhóm - bạn có thể chia 3 chữ số, mỗi 10 chữ số, mỗi chữ số 1, vậy tại sao không phải 0 chữ số?

Điều thú vị là các mã đã thay đổi cho .NET 4 - đây là sản phẩm có liên quan từ Reflector cho tôi:

else 
{ 
    if (((currencySymbol == null) || 
     ((chPtr2 = MatchChars(p, currencySymbol)) == null)) && 
     ((ansiCurrencySymbol == null) || 
     ((chPtr2 = MatchChars(p, ansiCurrencySymbol)) == null))) 
    { 
     break; 
    } 
    num |= 0x20; 
    currencySymbol = null; 
    ansiCurrencySymbol = null; 
    p = chPtr2 - 1; 
}