如何编写允许编译以下代码的 C# 代码:
var date = 8.September(2013); // Generates a DateTime for the 8th of September 2013
您可以使用扩展方法:
public static class MyExtensions
{
public static DateTime September(this int day, int year)
{
return new DateTime(year, 9, day);
}
}
但是,这通常是不好的做法,我建议不要这样做,特别是对于像这样微不足道的事情——new DateTime(2013, 9, 8)
真的比8.September(2013)
? 有时这种技巧可能对练习有用或有趣,但应谨慎使用。
我建议不要这样做,因为我觉得它的风格很差。也就是说,如果您真的想静态地执行此操作,则需要定义十二种不同的扩展方法(每个月名称一个),如下所示:
public static class DateConstructionExtensions
{
public static DateTime January(this int day, int year)
{
return new DateTime(year, /* month: */1, day);
}
// equivalent methods for February, March, etc...
}
你可以通过扩展来做到这一点:
public static DateTime September(this int day, int year) {
return new DateTime(year, 9, day);
}
当然,您需要 12 个这样的扩展,每个月一个。
我认为你可以有这样的实现:
public partial interface IMonth {
int Number {
get;
}
}
public partial class February: IMonth {
public int Number {
get {
return 2;
}
}
}
public static partial class Extensions {
public static DateTime OfMonth<T>(this int day, int year)
where T: IMonth, new() {
var month=new T();
var daysInMonth=DateTime.DaysInMonth(year, month.Number);
if(1>day||day>daysInMonth)
throw new ArgumentException();
return new DateTime(year, month.Number, day);
}
}
我之所以将月份声明为类,是因为月份在不同的文化中可能有不同的名称。您可能希望为它们提供不同的别名。
然后,由于存在IMonth
,是一个必须几个月才能执行的合同。扩展方法的约束new()
是为了避免IMonth
使用自身或抽象类。
此实现还检查有效的天数。
您可以将变量分配date
为:
var date=(28).OfMonth<February>(2013);
有道理?