【问题标题】:How to use int.TryParse with nullable int? [duplicate]如何将 int.TryParse 与可为空的 int 一起使用? [复制]
【发布时间】:2011-03-24 09:00:33
【问题描述】:

我正在尝试使用 TryParse 来查找字符串值是否为整数。如果该值为整数,则跳过 foreach 循环。这是我的代码。

string strValue = "42 "

 if (int.TryParse(trim(strValue) , intVal)) == false
 {
    break;
 }

intVal 是 int?(可为空的 INT)类型的变量。如何将 Tryparse 与可为空的 int 一起使用?

【问题讨论】:

    标签: c#


    【解决方案1】:

    这是一个使用 TryParse 的可空 int 选项

    public int? TryParseNullable(string val)
    {
        int outValue;
        return int.TryParse(val, out outValue) ? (int?)outValue : null;
    }
    

    【讨论】:

    • 我喜欢这个版本,因为“0”返回 0,“hello”返回 null。在接受的答案中,区别消失了。
    • 我不喜欢他的回答,因为它丢失了表示解析成功/失败的返回值。这是 Try* 方法的一个重要特性。
    • @frattaro 我真的不明白为什么这个答案可能不好。尝试解析失败时默认返回 0,在此示例中它只是返回 null。
    • 有了C#7就更简单了,不需要函数,一行就够了:int? myVal = int.TryParse(toCheck, out int tmp) ? (int?)tmp : null;
    • @frattaro 这有一个指示解析失败 - null。
    【解决方案2】:

    很遗憾,如果不使用另一个变量,您将无法做到这一点 - 因为 out 参数的类型必须与参数完全匹配。

    类似于 Daniel 的代码,但在第二个参数、修剪和避免与布尔常量比较方面进行了固定:

    int tmp;
    if (!int.TryParse(strValue.Trim(), out tmp))
    {
        break;
    }
    intVal = tmp;
    

    【讨论】:

    • @JonSkeet - strValue 可以为 null 并且 Trim() 方法会导致异常。只是说。 :)
    • @ShaktiPrakashSingh:我们不知道strValue 是否可以为空。如果它来自文本框,它可能不能为空。我的代码没有尝试解决这个问题,但我们真的不知道它是否应该解决它。
    • 为什么不反转if?例如:if (int.TryParse(Request["idParent"], out tmp)) idParent = tmp;(否则为空)
    • @JonSkeet 值得注意的是,我认为,虽然您的代码与提问者所要求的完全匹配(因为它很可能是关于循环/中断条件),但如果有人试图天真地在非-loop 场景在 strValue 无法解析为 int 的情况下,它们最终会以 0 作为 intVal 而不是 null。当然,你不应该仅仅因为一个答案被接受就从互联网上复制/粘贴^_^。
    • 使用 c#7 是一行:int? myVal = int.TryParse(toCheck, out int tmp) ? (int?)tmp : null;
    【解决方案3】:

    无法阻止自己制作通用版本。用法如下。

        public class NullableHelper
        {
            public delegate bool TryDelegate<T>(string s, out T result);
    
            public static bool TryParseNullable<T>(string s, out T? result, TryDelegate<T> tryDelegate) where T : struct
            {
                if (s == null)
                {
                    result = null;
                    return true;
                }
    
                T temp;
                bool success = tryDelegate(s, out temp);
                result = temp;
                return success;
            }
    
            public static T? ParseNullable<T>(string s, TryDelegate<T> tryDelegate) where T : struct
            {
                if (s == null)
                {
                    return null;
                }
    
                T temp;
                return tryDelegate(s, out temp)
                           ? (T?)temp
                           : null;
            } 
        }
    
    
    bool? answer = NullableHelper.ParseNullable<bool>(answerAsString, Boolean.TryParse);
    

    【讨论】:

      【解决方案4】:

      您可以创建一个辅助方法来解析可为空的值。

      示例用法:

      int? intVal;
      if( !NullableInt.TryParse( "42", out intVal ) )
      {
          break;
      }
      

      辅助方法:

      public static class NullableInt
      {
          public static bool TryParse( string text, out int? outValue )
          {
              int parsedValue;
              bool success = int.TryParse( text, out parsedValue );
              outValue = success ? (int?)parsedValue : null;
              return success;
          }
      }
      

      【讨论】:

        【解决方案5】:

        您也可以为此目的制作扩展方法;

        public static bool TryParse(this object value, out int? parsed)
        {
            parsed = null;
            try
            {
                if (value == null)
                    return true;
        
                int parsedValue;
                parsed = int.TryParse(value.ToString(), out parsedValue) ? (int?)parsedValue : null;
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        

        我在object 类型上做了一个扩展,但它同样可以在string 上。就我个人而言,我喜欢这些解析器扩展可在任何对象上使用,因此扩展名为 object 而不是 string

        使用示例:

        [TestCase("1", 1)]
        [TestCase("0", 0)]
        [TestCase("-1", -1)]
        [TestCase("2147483647", int.MaxValue)]
        [TestCase("2147483648", null)]
        [TestCase("-2147483648", int.MinValue)]
        [TestCase("-2147483649", null)]
        [TestCase("1.2", null)]
        [TestCase("1 1", null)]
        [TestCase("", null)]
        [TestCase(null, null)]
        [TestCase("not an int value", null)]
        public void Should_parse_input_as_nullable_int(object input, int? expectedResult)
        {
            int? parsedValue;
        
            bool parsingWasSuccessfull = input.TryParse(out parsedValue);
        
            Assert.That(parsingWasSuccessfull);
            Assert.That(parsedValue, Is.EqualTo(expectedResult));
        }
        

        不利的一面是这会破坏用于解析值的框架语法;

        int.TryParse(input, out output))
        

        但我喜欢它的较短版本(是否更具可读性可能需要讨论);

        input.TryParse(out output)
        

        【讨论】:

        • 如果您这样做,您将被锁定到TryParse,仅限intdouble 呢?还是bool
        • @FMM 有点晚了,但是,如果你想要的话,可以为它们编写一个单独的扩展方法。不确定您的意思是“锁定”其他扩展方法会有不同的签名
        • T 对于结构可以隐式转换为 T?。这是矫枉过正。
        猜你喜欢
        • 2017-12-09
        • 2012-06-16
        • 1970-01-01
        • 1970-01-01
        • 2017-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-07
        相关资源
        最近更新 更多