【问题标题】:C# Casting vs. ParseC# Casting 与 Parse
【发布时间】:2010-09-08 20:54:06
【问题描述】:

以下哪个是 C# 中更好的代码,为什么?

((DateTime)g[0]["MyUntypedDateField"]).ToShortDateString()

DateTime.Parse(g[0]["MyUntypedDateField"].ToString()).ToShortDateString()

最终,是转换好还是解析好?

【问题讨论】:

    标签: c# datetime parsing string casting


    【解决方案1】:

    如果 g[0]["MyUntypedDateField"] 确实是一个 DateTime 对象,那么强制转换是更好的选择。如果它不是真正的 DateTime,那么您别无选择,只能使用 Parse(如果您尝试使用强制转换,则会收到 InvalidCastException)

    【讨论】:

    • 当对象不是 DateTime 时,不要使用 Parse,而是使用 ParseExact 并指定预期的日期和时间格式,以避免依赖于当前的用户文化设置。请参阅我对这个问题的回答。
    【解决方案2】:

    选角是唯一好的答案。

    您必须记住,ToString 和 Parse 结果并不总是准确的 - 在某些情况下,您无法在这两个函数之间安全地往返。

    ToString 的文档说,它使用当前的线程文化设置。 Parse 的文档说,它还使用当前的线程文化设置(到目前为止一切都很好 - 它们使用相同的文化),但有一个明确的评论,即:

    格式受当前 DateTimeFormatInfo 对象的属性影响,默认情况下,这些属性派生自控制面板中的区域和语言选项项。 Parse 方法可能意外抛出 FormatException 的一个原因是当前 DateTimeFormatInfo.DateSeparator 和 DateTimeFormatInfo.TimeSeparator 属性设置为相同的值。

    因此,根据用户设置,ToString/Parse 代码可能并且将会意外失败...

    【讨论】:

      【解决方案3】:

      您的代码表明该变量可能是日期或看起来像日期的字符串。您可以通过强制转换简单地返回日期,但必须解析字符串。解析有两个注意事项;

      1. 如果您不确定是否可以解析此字符串,请使用DateTime.TryParse()

      2. 始终包含对您要解析为的文化的引用。 ToShortDateString() 在不同的地方返回不同的输出。您几乎肯定会希望使用相同的文化进行解析。我建议这个函数处理这两种情况;

        private DateTime ParseDateTime(object data)
        {
            if (data is DateTime)
            {
                // already a date-time.
                return (DateTime)data;
            }
            else if (data is string)
            {
                // it's a local-format string.
                string dateString = (string)data;
                DateTime parseResult;
                if (DateTime.TryParse(dateString, CultureInfo.CurrentCulture,
                                      DateTimeStyles.AssumeLocal, out parseResult))
                {
                    return parseResult;
                }
                else
                {
                    throw new ArgumentOutOfRangeException("data", 
                                       "could not parse this datetime:" + data);
                }
            }
            else
            {
                // it's neither a DateTime or a string; that's a problem.
                throw new ArgumentOutOfRangeException("data", 
                                      "could not understand data of this type");
            }
        }
        

      然后这样调用;

      ParseDateTime(g[0]["MyUntypedDateField").ToShortDateString();
      

      请注意,不良数据会引发异常,因此您需要捕获它。

      还有; 'as' 运算符不适用于 DateTime 数据类型,因为它仅适用于引用类型,而 DateTime 是一种值类型。

      【讨论】:

        【解决方案4】:

        正如@Brian R. Bondy 所指出的,这取决于 g[0]["MyUntypedDateField"] 的实现。安全的做法是使用 DateTime.TryParseas 运算符。

        【讨论】:

        • 让我们避免编写防御性代码。当提供的值具有不同的格式或类型时,开发人员应该知道预期的类型/格式和失败(例如抛出异常)。 TryParse 应在用户提供的输入中使用。
        • “让我们避免编写防御性代码”听过百万次。通常它会以“该死!他们改变了内部实现!”而告终!
        • @qbeuek ..不应该是“宽进严出”吗?
        • 这句话的原作者的意思不是“自动弄清楚”源数据是什么,这会导致规则模棱两可和未定义的结果,而是“接受尽可能多的明确定义的格式”。跨度>
        【解决方案5】:

        Parse 需要一个字符串作为输入,强制转换需要一个对象,因此在您上面提供的第二个示例中,您需要执行两次强制转换:一次从对象到字符串,然后从字符串到 DateTime。第一个没有。

        但是,如果在执行强制转换时存在异常风险,那么您可能希望采用第二条路线,以便可以 TryParse 并避免抛出代价高昂的异常。否则,走最有效的路线,只转换一次(从对象到 DateTime)而不是两次(从对象到字符串再到 DateTime)。

        【讨论】:

          【解决方案6】:

          【讨论】:

            猜你喜欢
            • 2016-01-22
            • 1970-01-01
            • 1970-01-01
            • 2015-10-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多