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)
有没有办法避免提及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等中使用这些解析方法.此外,这似乎更像是一个"实用程序"而不是应该出现的东西作为字符串本身的内置功能,这就是为什么我个人更喜欢它的单独类.