我现在正在处理一些遗留代码,这些代码通常使用try
+catch
和Convert.ToDecimal(someString)
(例如)来尝试将字符串转换为小数。由于某些原因,我必须使用这样的设置,即在调试时,我会在每个抛出的异常(不仅仅是用户未处理的异常)处停止,所以这很烦人,我尽可能地将其更改为使用TryParse
方法。
现在我所处的情况是有一个object
值和一个目标Type
,我只想知道是否可以将该值转换为目标类型。现在这样做如下:
try
{
Convert.ChangeType(val, targetType);
}
catch
{
// Do something else
}
实际结果并不重要,也不会进一步使用。
正如我所说,虽然这段代码现在正在运行,但它有点烦人,所以我想知道:有没有其他方法可以在不捕获异常的情况下完成上述操作
我在Type
上想到了类似IsAssignableFrom
的东西,但这似乎不适用于我的情况(我不想赋值,我想知道是否可以显式转换)。
如果你的意思是铸造,那么你可以使用is
关键字,比如:
object someObject = GetSomeObject();
if (someObject is string)
{
..
}
但请注意,casting和Convert.ChangeType
并不相同。例如,不能将字符串强制转换为int:
string numberString = "15";
int number = (int)numberString;
但你可以使用ChangeType
:
string numberString = "15";
int number = (int)Convert.ChangeType(numberString, typeof(int));
编辑:
如果你需要测试一个变量是否可以转换为特定类型,那么为什么不把try-catch
和Convert.ChangeType
包装成一个测试方法呢:
public bool IsConvertibleTo<T>(object value)
{
try
{
T convertedValue = (T)Convert.ChangeType(value, typeof(T));
return true;
}
catch (InvalidCastException)
{
return false;
}
catch (FormatException)
{
return false;
}
catch (OverflowException)
{
return false;
}
}
我将为您提供一个"隐藏"异常的解决方案。有时,捕获异常是必要的,正如您所说,这很烦人,因为调试器会在每个异常时停止。我知道,但有一种方法可以做到:
[DebuggerStepThrough]
public bool CanChangeType(this object instance, Type targetType)
{
try
{
Convert.ChangeType(val, targetType);
return true;
}
catch
{
return false;
}
}
诀窍在于DebuggerStepThrough
-属性。
但请记住,您永远无法调试到这样的方法中。如果不删除属性,就不会修复错误。知道一个方法应该很短——非常短,并且显然应该没有所有错误。
我对在关闭时抛出异常的Udp类也有同样的问题。将此短代码提取到一个不包含错误的单独方法中效果良好。
如果你想检查val
的类型,你应该像这样使用关键字is
,
if (val is targetType) {
...
}
如果你想将val
转换为类型targetType
,你应该像这样使用关键字as
,
targetType result = val as targetType;
if (result != null) {
...
}
他们两个都不会抛出异常
链接:https://msdn.microsoft.com/zh-cn/library/cscsdfbt.aspx
您最初的猜测是正确的。
public static bool CanChangeType(Type type)
{
return typeof (IConvertible).IsAssignableFrom(type);
}
是按类型检查Convert.ChangeType是否工作的正确方法(如异常消息通常所示)。不知道为什么你反对这个方法,因为它的名称中有"Assign"。它只是对类型进行一些检查。除此之外,它实际上不做任何分配。