我想在c#中解析一个字符串为可空int。ie。我想返回字符串的int值或null,如果它不能被解析。

我有点希望这能起作用

int? val = stringVal as int?;

但这行不通,我现在要做的是写这个扩展方法

public static int? ParseNullableInt(this string value)
{
    if (value == null || value.Trim() == string.Empty)
    {
        return null;
    }
    else
    {
        try
        {
            return int.Parse(value);
        }
        catch
        {
            return null;
        }
    }
}   

有更好的办法吗?

编辑:感谢TryParse的建议,我确实知道这一点,但它的工作原理是一样的。我更感兴趣的是知道是否有一个内置的框架方法,将直接解析成一个可空的int?


当前回答

我觉得我的解决方案是一个非常干净和漂亮的解决方案:

public static T? NullableParse<T>(string s) where T : struct
{
    try
    {
        return (T)typeof(T).GetMethod("Parse", new[] {typeof(string)}).Invoke(null, new[] { s });
    }
    catch (Exception)
    {
        return null;
    }
}

当然,这是一个通用的解决方案,只需要泛型参数有一个静态方法“Parse(string)”。这适用于数字,布尔值,日期时间等。

其他回答

我想出了这个方法,它满足了我的要求(我希望我的扩展方法尽可能地模拟框架的TryParse的返回,但是没有try{} catch{}块,并且没有编译器抱怨在框架方法中推断出可空类型)

private static bool TryParseNullableInt(this string s, out int? result)
{
    int i;
    result = int.TryParse(s, out i) ? (int?)i : null;
    return result != null;
}

格伦·斯拉文:我更想知道是否 有一个内置的框架方法 这将直接解析为 nullable int ?

如果值是有效的,如null或空字符串,则有这种方法将直接解析为可空的int(而不仅仅是int),但对于无效值抛出异常,因此您需要捕获异常并返回这些情况的默认值:

public static T Parse<T>(object value)
{
    try { return (T)System.ComponentModel.TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value.ToString()); }
    catch { return default(T); }
}

这种方法仍然可以用于非空解析和可空解析:

enum Fruit { Orange, Apple }
var res1 = Parse<Fruit>("Apple");
var res2 = Parse<Fruit?>("Banana");
var res3 = Parse<int?>("100") ?? 5; //use this for non-zero default
var res4 = Parse<Unit>("45%");

注意:在转换器上有一个IsValid方法,您可以使用它来代替捕获异常(如果预期抛出的异常会导致不必要的开销)。不幸的是,它只从。net 4开始工作,但仍然有一个问题,它在验证正确的DateTime格式时不检查您的语言环境,请参阅bug 93559。

我觉得我应该分享一下我的,更普通的。

用法:

var result = "123".ParseBy(int.Parse);

var result2 = "123".ParseBy<int>(int.TryParse);

解决方案:

public static class NullableParse
{
    public static Nullable<T> ParseBy<T>(this string input, Func<string, T> parser)
        where T : struct
    {
        try
        {
            return parser(input);
        }
        catch (Exception exc)
        {
            return null;
        }
    }

    public delegate bool TryParseDelegate<T>(string input, out T result);

    public static Nullable<T> ParseBy<T>(this string input, TryParseDelegate<T> parser)
        where T : struct
    {
        T t;
        if (parser(input, out t)) return t;
        return null;
    }
}

第一个版本比较慢,因为它需要一个试接,但它看起来更干净。如果它不会被多次调用无效字符串,那么它就不那么重要了。 如果性能是一个问题,请注意,当使用TryParse方法时,您需要指定ParseBy的类型参数,因为编译器不能推断它。我还必须定义一个委托,因为out关键字不能在Func<>中使用,但至少这次编译器不需要显式实例。

最后,你也可以将它与其他结构体一起使用,例如decimal、DateTime、Guid等。

如果没有必要,就不要使用异常——开销太大了。

TryParse的变体解决了这个问题——如果你想变得更有创意(让你的代码看起来更优雅),你可以在3.5中使用扩展方法做一些事情,但代码或多或少是一样的。

    public static void Main(string[] args)
    {

        var myString = "abc";

        int? myInt = ParseOnlyInt(myString);
        // null

        myString = "1234";

        myInt = ParseOnlyInt(myString);
        // 1234
    }
    private static int? ParseOnlyInt(string s)
    {
        return int.TryParse(s, out var i) ? i : (int?)null;
    }