1

有这个代码:

string abc = "123456";

要转换为 int,我应该使用 convert:

int abcInt = Convert.ToInt32(abc);

问题是,如果不是数字,我会看到返回零的异常,所以我的最终代码将如下所示:

try{ int abcInt = Convert.ToInt32(abc); }catch(Exception e){ int abcInt = 0; }

所以你看,我决定写一本书,让我成为一个对象,如果失败则返回零数字,这样可以保持最灵活的编程而没有太多垃圾代码:

int abcInt = Libs.str.safeInt(abc);

代码是:

public int safeInt(object ob)
{
    if ((ob == null) || (String.IsNullOrEmpty(ob.ToString())))
        return 0;
    try
    {
        return Convert.ToInt32(
            System.Text.RegularExpressions.Regex.Replace(ob.ToString(), @"@[^Ee0-9\.\,]+@i", "").
            ToString(CultureInfo.InvariantCulture.NumberFormat)
        );
    }
    catch (FormatException e)
    {
        return 0;
    }
}

但我想更进一步,做这样的事情:

int abcInt = (safeInt)abc;

怎么做?

无法将类型“字符串”转换为“Libs.safeInt.safeInt”

4

5 回答 5

5

应该只使用Int32.TryParse

int abcInt;
if(!Int32.TryParse(abc, out abcInt)) {
    abcInt = 0;
}
// abcInt has been parsed to an int, or defaulted to zero

请注意,这可以缩短为

int abcInt;
Int32.TryParse(abc, out abcInt);

如果您想要的只是默认值为零,因为

s当此方法返回时,如果转换成功,则包含与 中包含的数字等效的 32 位有符号整数值,如果转换失败,则返回零。如果s参数为null、格式不正确或表示小于MinValue或大于的数字,则转换失败MaxValue。此参数未初始化传递。

我实际上建议不要这样写,因为现在你无法区分abc = "0"and abc = "garbage"; 两者都表现出与上述两行代码完全相同的行为。使用上面的初始版本(即,如果需要if,您可以区分这两种情况;默默地忽略错误通常是个主意)。

也就是说,如果您非常想知道如何实现强制转换explicit运算符,您可以这样进行:

class SafeInt32 {
    private readonly int value;
    public int Value { get { return this.value; } }

    private readonly string source;
    public string Source { get { return this.source; } }

    private readonly bool successful;
    public bool Successful { get { return this.successful; } }

    public SafeInt32(string source) {
        this.source = source;
        this.successful = Int32.TryParse(source, out this.value);
    }

    public static explicit operator SafeInt32(string source) {
        return new SafeInt32(source);
    }

    public static implicit operator int(SafeInt32 safeInt32) {
        return safeInt32.Value;
    }
}

用法:

int abcInt = (SafeInt32)"123456";

请注意,我们必须定义一个显式转换运算符来将 astring转换为 a SafeInt32,并定义一个隐式转换运算符来将 aSafeInt32转换为 anint以获得所需的语法。后者是必要的,以便编译器可以静默地将 的结果转换(SafeInt32)"123456"int.

再次,我建议要这样做;使用Int32.TryParse.

于 2013-07-17T16:33:23.030 回答
1

您可以利用隐式和显式运算符来做您想做的事,是的。您还可以使用int.TryParse来避免对控制流使用异常。

public struct SafeInt
{
    public int Value { get; private set; }
    public static implicit operator int(SafeInt safeInt)
    {
        return safeInt.Value;
    }
    public static explicit operator SafeInt(string obj)
    {
        return new SafeInt() { Value = SafeParse(obj) };
    }
    public static int SafeParse(object value)
    {
        int output;
        int.TryParse((value ?? "0").ToString(), out output);
        return output;
    }
}
于 2013-07-17T16:39:02.547 回答
1

我的意思是,您应该使用int.TryParse,但是如果您对强制转换语法一无所知:

public class SafeInt
{
    private int _value;
    private SafeInt() {}
    public static explicit operator SafeInt(string str)
    {
        int x;
        int.TryParse(str, out x);
        SafeInt si = new SafeInt();
        si._value = x;
        return si;
    }
    public static implicit operator int(SafeInt x)
    {
        return x._value;
    }
    public override string ToString()
    {
        return _value.ToString();
    }
}

然后你可以像这样使用它:

int x = (SafeInt)"234234";
于 2013-07-17T16:42:26.817 回答
0

首先,让我继续记录在案,您可能不想这样做。

默默地忽略这样的问题可能会导致其他类型的问题,例如客户问“为什么这里的总数总是错误的?”。

话虽如此,在我给你一个更好的选择之前,让我们看看你如何做你想做的事:

void Main()
{
    int a = (SafeInt)"123";
    a.Dump();

    int b = (SafeInt)"xyz";
    b.Dump();
}

public struct SafeInt
{
    private readonly int _Value;

    public SafeInt(int value)
    {
        _Value = value;
    }

    public SafeInt(int? value)
    {
        _Value = value ?? 0;
    }

    public int Value
    {
        get
        {
            return _Value;
        }
    }

    public static implicit operator int(SafeInt s)
    {
        return s.Value;
    }

    public static implicit operator SafeInt(string s)
    {
        try
        {
            return new SafeInt(Convert.ToInt32(s));
        }
        catch (FormatException)
        {
            return new SafeInt();
        }
    }
}

这将打印出:

123
0

现在,我的建议是远离这个。相反,使用这个:

void Main()
{
    TryParse("123").Dump();
    TryParse("xyz").Dump();
}

public static int TryParse(string s, int errorValue = 0)
{
    int result;
    if (int.TryParse(s, out result))
        return result;
    return errorValue;
}

请注意,如果您总是希望 0 作为在错误时返回的值,那么系统中甚至还有一种更简单的方法,即:

int value;
int.TryParse("123", out value);

这里我们忽略 的布尔结果TryParse,因为如果 TryParse 失败,它会将参数设置为 0

于 2013-07-17T16:38:50.270 回答
0

我建议你不要这样做。与更简单的静态方法和/或构造函数相比,我发现显式和隐式转换很难发现、阅读和使用。另外,你知道int.TryParse方法吗?这对您来说可能是一个更好的解决方案:

public static int SafeInt(object value)
{
    int i;
    int.TryParse(value.ToString(), out i);
    return i;
}

或者,更直接地回答您的问题,您可以在类上使用显式和隐式转换SafeInt来执行此操作:

public class SafeInt
{
    public int Value { get; set; }
    public static implicit operator int(SafeInt si)
    {
        return si.Value;
    }
    public static explicit operator SafeInt(String str)
    {
        return new SafeInt { Value = Libs.str.safeInt(str) };
    }
}

像这样使用:

int i = (SafeInt)"123";
于 2013-07-17T16:39:30.363 回答