【问题标题】:TryParse Nullable types generically [duplicate]TryParse Nullable 类型通常[重复]
【发布时间】:2013-05-26 22:26:36
【问题描述】:

我为以下Nullable类型编写了重载的静态TryParse方法:int?short?long?double?DateTime?decimal?float?、@98764 @、byte?char?。下面是一些实现:

protected static bool TryParse(string input, out int? value)
{
    int outValue;
    bool result = Int32.TryParse(input, out outValue);
    value = outValue;
    return result;
}

protected static bool TryParse(string input, out short? value)
{
    short outValue;
    bool result = Int16.TryParse(input, out outValue);
    value = outValue;
    return result;
}

protected static bool TryParse(string input, out long? value)
{
    long outValue;
    bool result = Int64.TryParse(input, out outValue);
    value = outValue;
    return result;
}

每个方法的逻辑都是相同的,只是它们使用不同的类型。难道不能使用泛型,这样我就不需要那么多冗余代码了吗?签名看起来像这样:

bool TryParse<T>(string input, out T value);

谢谢

【问题讨论】:

  • 泛型方法不适用的一个原因是并非所有structs 都有TryParse 方法,但是您不能使用泛型约束在编译时只允许兼容类型。
  • 顺便说一下,您在提议的方法签名中缺少第二个 T 之后的 ?

标签: c# .net parsing generics type-conversion


【解决方案1】:

顺便说一句,你可以重构你的代码:

public static bool TryParse(string input, out int? value)
{
    return TryParse(input, Int32.TryParse, out value);
}

protected static bool TryParse(string input, out short? value)
{
    return TryParse(input, Int16.TryParse, out value);
}

protected static bool TryParse(string input, out long? value)
{
    return TryParse(input, Int64.TryParse, out value);
}

private static bool TryParse<T>(string input, TryParseFunc<T> tryParse, out T? value)
    where T : struct
{
    T outValue;
    bool result = tryParse(input, out outValue);
    value = outValue;
    return result;
}

private delegate bool TryParseFunc<T>(string input, out T value);

【讨论】:

  • 我喜欢。那很整齐。这也使我建议的更改非常简单 - 您只需在实现部分的第三行使用value = result ? outValue : (T?) null
  • 这很棒。谢谢!正如 Jon 建议的那样,还将包括 null 默认值。
  • 应该有一个徽章,用于发布@JonSkeet 本人在评论中批准的答案。
【解决方案2】:

您可以使用以下通用扩展方法,

public static Nullable<TSource> TryParse<TSource>(this string input) where TSource : struct
{
    try
    {
        var result = Convert.ChangeType(input, typeof(TSource));
        if (result != null)
        {
            return (TSource)result;
        }
        return null;
    }
    catch (Exception)
    {
        return null;
    }
}

以下调用将返回可空解析类型。

string s = "510";
int? test = s.TryParse<int>();
//TryParse Returns 510 and stored in variable test.

string s = "TestInt";
int? test = s.TryParse<int>();
//TryParse Returns null and stored in variable test.

【讨论】:

    【解决方案3】:

    难道不能使用泛型,这样我就不需要那么多冗余代码了吗?

    您可以通过反射来做到这一点,但这会相对较慢。否则,您可以创建一个从类型到“用于该类型的方法”的映射,但这会非常难看。除此之外,它永远不会是真正的通用的——它只适用于提供正确签名的TryParse 方法的类型,而这在编译时是未知的。 p>

    顺便说一句,我个人会考虑更改签名和行为。目前即使value 的类型是可以为空的,它在方法的末尾永远不会有空值,即使你返回false。为什么不将返回值作为解析操作的结果,失败返回null

    protected static long? TryParseInt64(string input)
    {
        long outValue;
        return Int64.TryParse(input, out outValue) ? (long?) outValue : null;
    }
    

    【讨论】:

    • 在这种情况下,我会远离泛型。关于您的建议,我需要签名采用bool TryParse(string input, out object value) 的形式,以便与.NET 的TryParse 方法保持一致。
    • @davenewza: 那么你应该至少改变行为,如果resultfalse,那么valuenull,与另一个保持一致TryParse 方法:out 参数在返回 false 时应始终具有类型的默认值(对于可空类型为 null)。
    • 啊,当然。感谢您指出这一点。
    • 你的方法不对。它应该解析一个 Nullable Int64,因此传递 "null" 字符串应该是成功的,在这种情况下 "null""foobar" 将产生相同的结果。跨度>
    • @AhmedKRAIEM,您提出的方法与问题中的方法不同。我认为您的评论应该针对撰写问题的人;这是他们的要求,而不是 Jon 的要求。
    猜你喜欢
    • 2019-05-31
    • 2020-08-11
    • 2015-02-13
    • 2011-12-01
    • 2011-06-13
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    相关资源
    最近更新 更多