2011-02-07 39 views
7

Tôi gặp sự cố khi TryParse hoạt động chính xác cho tôi. Tôi có một danh sách các giá trị mà tôi gần như chắc chắn là hợp lệ (khi chúng đến từ một thành phần khác trong hệ thống của chúng tôi) nhưng tôi muốn đảm bảo có lỗi xử lý đúng tại chỗ.TryParse thất bại với số âm

Dưới đây là một danh sách ví dụ về giá trị của tôi:

20,00
20,00
-150,00

Và đây là phương pháp tôi ban đầu đã viết:

private decimal CalculateValue(IEnumerable<XElement> summaryValues) 
     { 
      decimal totalValue = 0; 

      foreach (XElement xElement in summaryValues) 
      { 
       decimal successful; 
       Decimal.TryParse(xElement.Value, out successful); 
       if (successful > 0) 
        totalValue += Decimal.Parse(xElement.Value); 
      } 
      return totalValue; 
     } 

Biến 'thành công' đã trả về false cho -150,00, vì vậy tôi đã thêm NumberStyles:

private decimal CalculateValue(IEnumerable<XElement> summaryValues) 
     { 
      decimal totalValue = 0; 

      foreach (XElement xElement in summaryValues) 
      { 
       decimal successful; 
       Decimal.TryParse(xElement.Value, NumberStyles.AllowLeadingSign, null, out successful); 
       if (successful > 0) 
        totalValue += Decimal.Parse(xElement.Value, NumberStyles.AllowLeadingSign); 
      } 
      return totalValue; 
     } 

Tuy nhiên, bây giờ tôi có NumberStyles trong đó, không có số nào sẽ phân tích cú pháp! Tôi cảm thấy tốt khi có IFormatProvider được đặt thành null vì đây là tất cả trong hệ thống của chúng tôi. Có ai nhìn thấy những gì tôi có thể làm sai?

+2

Tại sao các bạn phân tích nó hai lần? – SLaks

Trả lời

3

Những câu trả lời khác đã có ý tưởng đúng liên quan đến các cách thích hợp để sử dụng Decimal.TryParse với. Tuy nhiên, nếu tôi đang viết các phương pháp trong câu hỏi, tôi muốn sử dụng LINQ để làm việc với các đối tượng LINQ-to-XML:

private decimal CalculateValue(IEnumerable<XElement> summaryValues) 
{ 
    return summaryValues 
     .Sum(el => 
      { 
       decimal value; 
       if (Decimal.TryParse(el.Value, out value)) 
        return value; 
       return 0M; 
      }); 
} 

phiên bản này hoạt động một cách chính xác như nhau, nhưng nó sử dụng phương pháp Enumerable.Sum để tính toán toàn bộ. Tất cả tôi phải cung cấp là một hàm nội tuyến chiết xuất các giá trị thập phân từ một XElement.

+0

Cảm ơn, tôi đã sử dụng mã này. – Jeannine

11

Đây không phải là cách bạn định sử dụng TryParse.

TryParse trả về một boolean (đúng/sai), do đó, mã của bạn ở trên nên là:

private decimal CalculateValue(IEnumerable<XElement> summaryValues) 
     { 
      decimal totalValue = 0; 

      foreach (XElement xElement in summaryValues) 
      { 
       decimal valueReturned; 
       bool successful = Decimal.TryParse(xElement.Value, out valueReturned); 
       if (successful) 
        totalValue += valueReturned; 
      } 
      return totalValue; 
     } 

hoặc ngắn gọn hơn,

private decimal CalculateValue(IEnumerable<XElement> summaryValues) 
     { 
      decimal totalValue = 0; 

      foreach (XElement xElement in summaryValues) 
      { 
       decimal valueReturned; 
       if (Decimal.TryParse(xElement.Value, out valueReturned)) 
        totalValue += valueReturned; 
      } 
      return totalValue; 
     } 
+1

'if (! Decimal.TryParse (/ * derp * /) ném InvalidOperationException mới (" OMG WTF LOL ")' – Will

+0

@Will Trong ví dụ này, anh ta nên có một ngoại lệ như thế này, nếu anh ta hợp lý tin tưởng nguồn. Nhưng bạn có thể có một tình huống mà bạn mong đợi và muốn âm thầm bỏ qua những chuỗi không phân tích cú pháp –

1

thành công của bạn sẽ là tiêu cực đối với một giá trị âm đang được phân tích cú pháp. if (successful > 0) của bạn là điều khiến bạn khó chịu.

Nếu họ đang gần như một cách tích cực sẽ là giá trị hợp lệ, hãy thử sử dụng Convert.ToDecimal:

decimal val = Convert.ToDecimal(xElement.Value); 

Nếu không, thay đổi logic của bạn một chút để được nhiều hơn như:

decimal val; 
if (Decimal.TryParse(xElement.Value, out val)){ 
    // valid number 
} 
0

tôi sẽ đề nghị bạn cho XElement biết giá trị nút nào cần tìm kiếm như sau:

XElement.Element("nodename").Value 

Instea d của XElement.Value. ít nhất đó là những gì tôi sẽ làm :)

4

Những người khác đang giải thích cách làm đúng, nhưng không thực sự giải thích những gì bạn đang làm sai.

Nơi bạn đang sử dụng "thành công" ở trên không phải là giá trị thành công, đó là số thực đang được phân tích cú pháp. Vì vậy, nếu bạn phân tích cú pháp "-150.00" tất nhiên thành công sẽ là số âm. Giá trị ngoài của TryParse là giá trị được phân tích thực tế và boolean cho biết liệu quá trình có thành công hay không là giá trị trả về. Sử dụng những gì bạn cần để hiểu sẽ là một cái gì đó như:

string inputValue = "-150.00"; 
decimal numericValue; 
bool isSucessful = Decimal.TryParse(inputValue , out numericValue); 

Trong trường hợp này, là thành công sẽ là TRUE, numericValue sẽ là -150.Khi bạn đang sử dụng các giá trị do người dùng cung cấp thay vì một hardcoded tôi đã sử dụng ở trên, bạn sẽ muốn kiểm tra:

if(isSuccessful) 
{ 
    // Do something with numericValue since we know it to be a valid decimal 
} 
else 
{ 
    // Inform User, throw exception, etc... as appropriate, Don't use numericValue because we know it's wrong. 
} 
+0

Vâng, đây là gốc của vấn đề. Cảm ơn bạn đã biên soạn tôi. :) – Jeannine

0

Đến từ Google. Câu trả lời cho tôi là văn hóa đến là sai - đặc biệt trong một tệp JSON đến.

Sử dụng

totalValue += decimal.Parse(xElement.Value, NumberStyles.Any, CultureInfo.InvariantCulture); 

hoặc

bool successful = decimal.TryParse(xElement.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out value); 
Các vấn đề liên quan