2011-09-22 30 views
27

Khi chuyển đổi ví dụ: decimal thành số string, bạn sử dụng số CultureInfo.InvariantCulture và chuyển nó làm IFormatProvider. Nhưng tại sao tình trạng quá tải này không ở trong số object?Tại sao đối tượng không có quá tải chấp nhận IFormatProvider?

Một thực hiện tốt sẽ là:

public virtual string ToString() 
{ 
    // yadayada, usual ToString 
} 

public virtual string ToString(IFormatProvider provider) 
{ 
    return ToString(); 
} 

Điều này sẽ không gây hại hay có lợi cho lớp object, nhưng đối tượng bắt nguồn từ nó thay vì có thể ghi đè lên tình trạng quá tải và nó sẽ được dễ dàng hơn rất nhiều để gọi nó khi bạn không chắc chắn về loại.

Sự cố khiến tôi gặp phải điều này là khi tôi đang tạo một phương thức có thể nhận tất cả các thuộc tính của một lớp và viết nó vào xml. Vì tôi không muốn kiểm tra loại đối tượng, tôi chỉ gọi là ToString. Nhưng điều này có phải là số thập phân hay không, đầu ra sẽ dựa trên số CurrentCulture của luồng, không phải là tối ưu. Cách giải quyết duy nhất tôi có thể thấy là thay đổi CurrentCulture thành InvariantCulture và sau đó thay đổi lại thành bất kỳ điều gì trước đây. Nhưng điều đó sẽ chỉ được xấu xí như tôi sẽ phải viết thử cuối cùng khối, vv

mã hiện tại của tôi là:

 foreach (var property in typeof(Order).GetProperties(BindingFlags.Public | BindingFlags.Instance). 
      Where(c => ValidTypes.Contains(c.PropertyType))) 
     { 
      var value = property.GetValue(order, null); 
      if (value != null) 
      { 
       writer.WriteElementString(property.Name, 
       value.ToString()); 
      } 
     } 

Nhưng tôi sẽ muốn nó được:

 foreach (var property in typeof(Order).GetProperties(BindingFlags.Public | BindingFlags.Instance). 
      Where(c => ValidTypes.Contains(c.PropertyType))) 
     { 
      var value = property.GetValue(order, null); 
      if (value != null) 
      { 
       writer.WriteElementString(property.Name, 
       value.ToString(CultureInfo.InvariantCulture)); 
      } 
     } 

Bất kỳ lợi ích không bị quá tải trên object?

Trả lời

28

Cố gắng đúc của bạn value để IFormattable:

foreach (var property in typeof(Order).GetProperties(BindingFlags.Public | BindingFlags.Instance). 
     Where(c => ValidTypes.Contains(c.PropertyType))) 
{ 
    var value = property.GetValue(order, null); 
    if (value != null) 
    { 
     var formattable = value as IFormattable; 
     writer.WriteElementString(property.Name, 
     formattable == null ? value.ToString() : formattable.ToString(null, CultureInfo.InvariantCulture)); 
    } 
} 
+3

'IConvertible' thực sự có ý nghĩa hơn – dlev

+5

@ dlev: Tôi không đồng ý - OP đặc biệt muốn * chỉ * định dạng. Cho rằng các loại có thể dễ dàng thực hiện IFormattable nhưng không IConvertible, và rằng phương pháp duy nhất trong IFormattable là chính xác là một trong những OP muốn gọi, tôi nghĩ rằng IFormattable có ý nghĩa hơn. –

+0

@Jon Dựa trên câu hỏi của OP, có vẻ như anh ta có kinh nghiệm thực sự sử dụng phiên bản 'IConvertible' của' ToString() ', đó là lý do tôi đề cập đến nó. Điểm của bạn được thực hiện tốt, mặc dù. – dlev

14

phương pháp khuyến nông Handy dung dịch Phêrô (sửa đổi để kiểm tra cũng cho IConvertible).

public static string ToInvariantString(this object obj) 
{ 
    return obj is IConvertible ? ((IConvertible)obj).ToString(CultureInfo.InvariantCulture) 
     : obj is IFormattable ? ((IFormattable)obj).ToString(null, CultureInfo.InvariantCulture) 
     : obj.ToString(); 
} 
8

Hãy thử một trong những:

string valueString = XmlConvert.ToString(value); 
string valueString = Convert.ToString(value, CultureInfo.InvariantCulture); 

XmlConvert.ToString() được thực hiện cho XML, vì vậy nó sẽ giữ cho mọi thứ gần gũi hơn với spec XML, chẳng hạn như sử dụng "true" thay vì "True ". Tuy nhiên, nó cũng giòn hơn Convert.ToString(). Ví dụ, điều này sẽ ném một ngoại lệ vì thời gian tính theo giờ UTC:

XmlConvert.ToString(DateTime.UtcNow) 

nhưng công trình này: (. Trừ khi bạn có kế hoạch để định dạng số)

XmlConvert.ToString(DateTime.UtcNow, "o") 
+2

Convert.ToString thực sự chuyển thành IConvertible và IFormattable (xem bài trước): chuỗi tĩnh công cộng ToString (Giá trị đối tượng, IFormatProvider provider) { IC icvertvert = giá trị như IConvertible; nếu (ic!= null) return ic.ToString (nhà cung cấp); Giá trị có thể định dạng IFormattable = giá trị như IFormattable; if (formattable! = Null) return formattable.ToString (null, nhà cung cấp); giá trị trả về == null? String.Empty: value.ToString(); } –

Các vấn đề liên quan