TypeConverter.IsValid() 使用当前线程文化,但 TypeConverter.ConvertFrom() 不使用? [英] TypeConverter.IsValid() uses current thread culture but TypeConverter.ConvertFrom() doesn't?
问题描述
似乎 TypeConverter.IsValid()
使用当前的线程文化,但 TypeConverter.ConvertFrom()
没有.
It seems that TypeConverter.IsValid()
uses the current thread culture but TypeConverter.ConvertFrom()
doesn't.
这使得将 TypeConverter.IsValid()
与 DateTime
类型一起使用变得非常无用,除非您处于不变文化中.确实,这似乎是一个错误.
This makes it pretty useless to use TypeConverter.IsValid()
with the DateTime
type unless you are in the invariant culture. Indeed, it seems to be a bug.
有谁知道如何让 TypeConverter.IsValid()
使用当前的文化?
Does anyone know how to make TypeConverter.IsValid()
use the current culture?
下面的代码演示了这个问题.
The following code demonstrates the problem.
它使用两个字符串,一个是 DD/MM/YYYY 格式,一个是 MM/DD/YYYY 格式.
It uses two strings, one in DD/MM/YYYY format and one in MM/DD/YYYY format.
测试的第一部分是在不变文化中完成的.它表明 TypeConverter.IsValid()
为 MM/DD/YYYY 字符串返回 true,并且您可以使用 TypeConverter.ConvertFrom()
将该字符串转换为 日期时间
.
The first part of the test is done in the Invariant Culture. It demonstrates that TypeConverter.IsValid()
returns true for the MM/DD/YYYY string and that you can use TypeConverter.ConvertFrom()
to convert that string to a DateTime
.
第一部分还演示了 TypeConverter.IsValid()
为 DD/MM/YYYY 字符串返回 false.
The first part also demonstrates that TypeConverter.IsValid()
returns false for the DD/MM/YYYY string.
对于第二部分,我更改了使用DD/MM/YYYY"日期的当前区域性en-GB".
For the second part, I change the current culture "en-GB" which uses "DD/MM/YYYY" dates.
我现在希望 IsValid()
结果被反转,但它返回与之前相同的两个字符串.所以它说 MM/DD/YYYY 字符串是有效的.
I would now expect the IsValid()
results to be reversed, but it returns the same as before for the two strings. So it says that the MM/DD/YYYY string is valid.
但是 - 这是重要的一点 - 如果您尝试使用 TypeConverter.ConvertFrom()
来实际转换 TypeConverter.IsValid()
说没问题的字符串,你会得到一个例外.
However - and this is the important bit - if you try to use TypeConverter.ConvertFrom()
to actually convert the string which TypeConverter.IsValid()
said was ok, you will get an exception.
有没有办法解决这个问题?
Is there a way to work around this?
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();
}
}
}
推荐答案
这是 TypeConverter.IsValid() 中的一个缺陷.类型转换器具有文化意识,其虚拟 ConvertFrom() 方法采用 CultureInfo 参数.您正在使用不带 CultureInfo 的非虚拟重载,因此您将获得由 CultureInfo.CurrentCulture 选择的转换.
It is a flaw in TypeConverter.IsValid(). A type converter is culture-aware, its virtual ConvertFrom() method takes a CultureInfo argument. You are using the non-virtual overload that doesn't take a CultureInfo so you'll get the conversion selected by CultureInfo.CurrentCulture.
TypeConverter.IsValid() 确实没有具有接受 CultureInfo 的重载.并清除它传递给 TypeConverter.ConvertFrom() 方法的 CultureInfo,它传递 CultureInfo.InvariantCulture.
TypeConverter.IsValid() does not have an overload that accepts a CultureInfo. And flubs the CultureInfo it passes to the TypeConverter.ConvertFrom() method, it passes CultureInfo.InvariantCulture.
很难为这种行为找到理由.可能是一个刚刚被发现太晚而无法做任何事情的错误.它肯定无法再修复了.
Hard to come up with a justification for this behavior. Probably a bug that just got noticed too late to do anything about. It certainly isn't fixable anymore.
解决方法是执行 IsValid() 所做的操作,但要指定正确的区域性.首先调用 CanConvertFrom(),然后在 try/catch 块中调用 ConvertFrom().
The workaround is to do what IsValid() does but by specifying the correct culture. First call CanConvertFrom(), then call ConvertFrom() in a try/catch block.
这篇关于TypeConverter.IsValid() 使用当前线程文化,但 TypeConverter.ConvertFrom() 不使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!