C# 有没有试试 Convert.ToInt32... 避免异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18227220/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a try Convert.ToInt32... avoiding exceptions
提问by Jeroen van Langen
I'd like to know if there is a "safe" way to convert an object to an int
, avoiding exceptions.
我想知道是否有一种“安全”的方法可以将对象转换为int
,从而避免异常。
I'm looking for something like public static bool TryToInt32(object value, out int result);
我正在寻找类似的东西 public static bool TryToInt32(object value, out int result);
I know I could make something like this:
我知道我可以做这样的事情:
public static bool TryToInt32(object value, out int result)
{
try
{
result = Convert.ToInt32(value);
return true;
}
catch
{
result = 0;
return false;
}
}
But I'd rather avoid exceptions, because they are slowing down the process.
但我宁愿避免例外,因为它们正在减慢进程。
I think this is more elegant, but it's still "cheap":
我认为这更优雅,但它仍然“便宜”:
public static bool TryToInt32(object value, out int result)
{
if (value == null)
{
result = 0;
return false;
}
return int.TryParse(value.ToString(), out result);
}
Does anyone have better ideas?
有人有更好的想法吗?
UPDATE:
更新:
This sounds a little like splitting hairs, but converting an object to string forces the implementer to create a clear ToString()
function. For example:
这听起来有点像分裂头发,但将对象转换为字符串会迫使实现者创建一个清晰的ToString()
函数。例如:
public class Percentage
{
public int Value { get; set; }
public override string ToString()
{
return string.Format("{0}%", Value);
}
}
Percentage p = new Percentage();
p.Value = 50;
int v;
if (int.TryParse(p.ToString(), out v))
{
}
This goes wrong, I can do two things here, or implement the IConvertable
like this:
这出错了,我可以在这里做两件事,或者IConvertable
像这样实现:
public static bool ToInt32(object value, out int result)
{
if (value == null)
{
result = 0;
return false;
}
if (value is IConvertible)
{
result = ((IConvertible)value).ToInt32(Thread.CurrentThread.CurrentCulture);
return true;
}
return int.TryParse(value.ToString(), out result);
}
But the ToInt32
method of the IConvertible
cannot be canceled. So if it's not possible to convert the value, an exception cannot be avoided.
但是ToInt32
方法IConvertible
不能被取消。因此,如果无法转换该值,则无法避免异常。
Or two: Is there a way to check if the object contains a implicit operator?
或者二:有没有办法检查对象是否包含隐式运算符?
This is very poor:
这是非常可怜的:
if (value.GetType().GetMethods().FirstOrDefault(method => method.Name == "op_Implicit" && method.ReturnType == typeof(int)) != null)
{
result = (int)value;
return true;
}
回答by ranieuwe
int variable = 0;
int.TryParse(stringValue, out variable);
If it can't be parsed, the variable will be 0. See http://msdn.microsoft.com/en-us/library/f02979c7.aspx
如果无法解析,则该变量将为 0。请参阅http://msdn.microsoft.com/en-us/library/f02979c7.aspx
回答by Ehsan
No need to re-invent the wheel here. use int.TryParseto achieve your goal. It returns a bool to show that value is parsed or not. and if parsed the result is saved in the output variable.
无需在这里重新发明轮子。使用int.TryParse来实现您的目标。它返回一个 bool 来显示值是否被解析。如果解析,结果将保存在输出变量中。
int result;
object a = 5;
if(int.TryParse(a.ToString(),out result))
{
Console.WriteLine("value is parsed"); //will print 5
}? ?
object b = a5;
if(int.TryParse(b.ToString(),out result))
{
? ?Console.WriteLine("value is parsed"); ?
}
else
{
Console.WriteLine("input is not a valid integer"); ?//will print this
}
回答by Lars Kristensen
I would use a mixture of what you are already doing;
我会混合使用你已经在做的事情;
- Check if the object is null - return false and the value 0;
- Attempt to convert directly - if successful, return true and the converted value
- Attempt to parse value.ToString() - if successfull, return true and the parsed value
- Any other case - Return false and the value 0, as object is not convertible/parsible
- 检查对象是否为空 - 返回 false 和值 0;
- 尝试直接转换 - 如果成功,返回 true 和转换后的值
- 尝试解析 value.ToString() - 如果成功,则返回 true 和解析的值
- 任何其他情况 - 返回 false 和值 0,因为对象不可转换/解析
The resulting code:
结果代码:
public static bool TryToInt32(object value, out int result)
{
result = 0;
if (value == null)
{
return false;
}
//Try to convert directly
try
{
result = Convert.ToInt32(value);
return true;
}
catch
{
//Could not convert, moving on
}
//Try to parse string-representation
if (Int32.TryParse(value.ToString(), out result))
{
return true;
}
//If parsing also failed, object cannot be converted or paresed
return false;
}
回答by xanatos
Spurring from the comments. The response is no. You can't do what Convert.ToInt32(object)
does without having throwed exceptions. You can do something similar (and you already did it). The only thing I would optimize is the case of value
already an int
.
来自评论的刺激。答案是否定的。如果不Convert.ToInt32(object)
抛出异常,您就无法执行该操作。你可以做类似的事情(而且你已经做到了)。我唯一要优化的是value
已经是int
.
if (value is int)
return (int)value;
You can't do as Convert.ToInt32(object)
because Convert.ToInt32(object)
doesn't simply test if value
is short, int, long, ushort, ...
and then cast them. It checks if the value
is IConvertible
. If yes it uses the IConvertible.ToInt32
. Sadly the interface IConvertible
is quite poor: it doesn't have non-throwing methods (IConvertible.Try*
)
你不能那样做,Convert.ToInt32(object)
因为Convert.ToInt32(object)
不简单地测试是否value
是short, int, long, ushort, ...
然后投射它们。它检查是否value
是IConvertible
。如果是,它使用IConvertible.ToInt32
. 遗憾的是,界面IConvertible
很差:它没有非抛出方法(IConvertible.Try*
)
While stupid (but perhaps not too much), someone could make for example a UnixDateTime
struct: (UnixTime is the number of seconds from midnight 1970-01-01), where the IConvertible.ToInt32
returns this number of seconds, while the ToString()
returns a formatted date. All the int.TryParse(value.ToString(), out parsed)
would choke, while the Convert.ToInt32
would work flawlessly.
虽然愚蠢(但也许不是太多),但有人可以制作例如一个UnixDateTime
结构体:(UnixTime 是从 1970-01-01 午夜开始的秒数),其中IConvertible.ToInt32
返回这个秒数,而ToString()
返回一个格式化的日期。所有的int.TryParse(value.ToString(), out parsed)
都会窒息,而它们Convert.ToInt32
会完美地工作。
回答by Jeremy Thomas
This version using a type converter would only convert to string as a last resort but also not throw an exception:
使用类型转换器的这个版本只会将转换为字符串作为最后的手段,但也不会抛出异常:
public static bool TryToInt32(object value, out int result)
{
if (value == null)
{
result = 0;
return false;
}
var typeConverter = System.ComponentModel.TypeDescriptor.GetConverter(value);
if (typeConverter != null && typeConverter.CanConvertTo(typeof(int)))
{
var convertTo = typeConverter.ConvertTo(value, typeof(int));
if (convertTo != null)
{
result = (int)convertTo;
return true;
}
}
return int.TryParse(value.ToString(), out result);
}
回答by Johan Larsson
I wrote this mess, looking at it makes me sad.
我写了这个烂摊子,看着它让我很难过。
using System;
using System.Globalization;
internal static class ObjectExt
{
internal static bool TryConvertToDouble(object value, out double result)
{
if (value == null || value is bool)
{
result = 0;
return false;
}
if (value is double)
{
result = (double)value;
return true;
}
var text = value as string;
if (text != null)
{
return double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out result);
}
var convertible = value as IConvertible;
if (convertible == null)
{
result = 0;
return false;
}
try
{
result = convertible.ToDouble(CultureInfo.InvariantCulture);
return true;
}
catch (Exception)
{
result = 0;
return false;
}
}
}
Edit Notice now I answered for double when the question was int, keeping it any way. Maybe useful for someone.
现在编辑注意,当问题是 int 时,我回答了 double,无论如何都要保留它。也许对某人有用。
回答by chris31389
Return a nullable int. that way you know whether you parsed 0.
返回一个可为空的 int。这样你就知道你是否解析了 0。
int? value = int.TryParse(stringValue, out int outValue)
? outValue
: default(int?);