如何编写通用扩展方法?

Arn*_*und 2 c# generics c#-4.0

我正在开发一个围绕TryParse的通用包装器,如下所示:

    public delegate bool ParseDelegate<T>(string s, out T result);

    public static T? ParseOrNull<T>(this string value, ParseDelegate<T> parse) where T : struct
    {
        T result;
        var parsed = parse(value, out result);
        return parsed ? result : (T?)null;
    }

    [Test]
    public void ParsesValidInt()
    {
        Assert.AreEqual(1234, "1234".ParseOrNull<int>(int.TryParse));
    }

    [Test]
    public void ParsesValidDecimal()
    {
        Assert.AreEqual(12.34M, "12.34".ParseOrNull<decimal>(decimal.TryParse));
    }
Run Code Online (Sandbox Code Playgroud)

这有点重复.有没有办法避免提及int.TryParse,所以我的调用如下所示:

"1234".ParseOrNull<int>()
Run Code Online (Sandbox Code Playgroud)

Ree*_*sey 6

有没有办法避免提及int.TryParse,所以我的调用如下所示:

不是直接的,因为TryParse它不是共享接口的一部分.如果存在这些值类型的共享接口,则可以通过约束来实现.


就个人而言,我不会建议使用扩展方法.我宁愿把它写成更像的东西:

public static class Parse
{
    public delegate bool ParseDelegate<T>(string s, out T result);
    public static T? FromString<T>(string value, ParseDelegate<T> parse) where T : struct
    {
        T result;
        var parsed = parse(value, out result);
        return parsed ? result : (T?)null;
    }
    public static int? ToNullableInt32(string value)
    {
        return FromString<int>(value, int.TryParse);
    }
    public static double? ToNullableDouble(string value)
    {
        return FromString<double>(value, double.TryParse);
    }
}
Run Code Online (Sandbox Code Playgroud)

这预先增加了一些开销,但允许你非常干净地写这些,即:

    int? first = Parse.FromString<int>("1234", int.TryParse);
    int? second = Parse.ToNullableInt32("1234");
    double? third = Parse.ToNullableDouble("1234");
Run Code Online (Sandbox Code Playgroud)

我认为放置扩展方法没什么价值,特别是在类似的东西string(随处可用),因为它"污染"了字符串本身的编译.你会在使用字符串的任何地方看到这一点 - 基本上,每当你使用这个命名空间时,你最终会在你的intellisense等中使用这些解析方法.此外,这似乎更像是一个"实用程序"而不是应该出现的东西作为字符串本身的内置功能,这就是为什么我个人更喜欢它的单独类.