2013-05-30 17 views
3

看來TypeConverter.IsValid()使用當前的線程文化,但TypeConverter.ConvertFrom()不使用。TypeConverter.IsValid()使用當前線程文化,但TypeConverter.ConvertFrom()不?

這使得使用TypeConverter.IsValid()DateTime類型相當無用,除非您處於不變文化中。確實,這似乎是一個錯誤。

有沒有人知道如何使TypeConverter.IsValid()使用當前的文化?

以下代碼演示了此問題。

它使用兩個字符串,一個是DD/MM/YYYY格式,一個是MM/DD/YYYY格式。

測試的第一部分是在不變文化中完成的。它演示TypeConverter.IsValid()對於MM/DD/YYYY字符串返回true,並且您可以使用TypeConverter.ConvertFrom()將該字符串轉換爲DateTime

第一部分還演示TypeConverter.IsValid()爲DD/MM/YYYY字符串返回false。

對於第二部分,我更改使用「DD/MM/YYYY」日期的當前文化「en-GB」。

我現在預計IsValid()的結果會被顛倒過來,但它對於兩個字符串返回的結果與以前一樣。所以它說MM/DD/YYYY字符串是有效的。

但是 - 這是重要的一點 - 如果您嘗試使用TypeConverter.ConvertFrom()來實際轉換TypeConverter.IsValid()表示可以的字符串,您將得到一個異常。

是否有辦法來解決此問題?

using System; 
using System.ComponentModel; 
using System.Globalization; 
using System.Threading; 

namespace Demo 
{ 
    class Program 
    { 
     void Run() 
     { 
      // Start off with the US culture, which has MM/DD/YYYY date format. 

      Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; 

      var dateConverter = TypeDescriptor.GetConverter(typeof(DateTime)); 
      var goodDateString = "07/19/1961"; 
      var badDateString = "19/07/1961"; 

      test(dateConverter, goodDateString, "DateTime"); // Says it's good. 
      test(dateConverter, badDateString, "DateTime"); // Says it's bad. 

      var dateTimeValue = (DateTime) dateConverter.ConvertFrom(goodDateString); 

      Console.WriteLine("dateTimeValue = " + dateTimeValue); 
      Console.WriteLine(); 

      // Now lets change the current culture to the UK, which has DD/MM/YYYY date format. 

      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB"); 
      dateConverter = TypeDescriptor.GetConverter(typeof(DateTime)); 

      test(dateConverter, goodDateString, "DateTime"); // Still says it's good. 
      test(dateConverter, badDateString, "DateTime"); // Still says it's bad. 

      // TypeConverter.IsValid(badDateString) returns false, so we shouldn't be able to convert it. 
      // Well, we can, like so: 

      dateTimeValue = (DateTime)dateConverter.ConvertFrom(badDateString); // Shouldn't work according to "IsValid()" 
      Console.WriteLine("dateTimeValue (bad) = " + dateTimeValue);  // But this is printed ok. 

      // TypeConverter.IsValid(goodDateString) returns true, so we can convert it right? 
      // Well, no. This now throws an exception, even though "IsValid()" returned true for the same string. 

      dateTimeValue = (DateTime)dateConverter.ConvertFrom(goodDateString); // This throws an exception. 
     } 

     void test(TypeConverter converter, string text, string type) 
     { 
      if (converter.IsValid(text)) 
       Console.WriteLine("\"" + text + "\" IS a valid " + type); 
      else 
       Console.WriteLine("\"" + text + "\" is NOT a valid " + type); 
     } 

     static void Main() 
     { 
      new Program().Run(); 
     } 
    } 
} 
+2

從記憶中,「不」突飛猛進。但我似乎記得有一些IsValid API的問題,並且在所有情況下都不能很好地工作。嘗試轉換並查看它是否有效可能是必要的。 –

+0

@MarcGravell Aye,這似乎是適當的行動 - 只是完全避免使用「IsValid()」。 –

回答

4

這是TypeConverter.IsValid()中的一個缺陷。一個類型轉換器是文化感知的,它的虛擬ConvertFrom()方法接受一個CultureInfo參數。您正在使用不使用CultureInfo的非虛擬重載,因此您將獲得由CultureInfo.CurrentCulture選擇的轉換。

TypeConverter.IsValid()does not有一個接受CultureInfo的重載。並將其傳遞給TypeInverter.ConvertFrom()方法的CultureInfo傳遞給它,它傳入CultureInfo.InvariantCulture。

很難想出這種行爲的理由。可能是一個剛剛注意到太遲而無法做任何事情的bug。它當然不能解決了。

解決方法是通過指定正確的文化來完成IsValid()的工作。首先調用CanConvertFrom(),然後在try/catch塊中調用ConvertFrom()。

+0

啊謝謝。你也預料到我會遇到另一個問題:*'「與使用IsValid()相比,使用異常捕獲錯誤效率更低 - 」幸運的是,現在我知道這沒什麼區別。 –