年份的参数类型
本文关键字:类型 参数 | 更新日期: 2023-09-27 18:16:25
我正在编写一个接受year作为参数的方法。即等于或小于当前年份的四位数。日历只有格里高利历(目前…我不确定未来),我肯定不需要任何BC。
我要使用哪种数据类型?显而易见的解决方案是使用DateTime或Int32:
public void MyFunction(DateTime date)
{
// year to work with: date.Year;
// date.Month, date.Day, etc. is irrelevant and will always be
}
或
public void MyFunction(Int year)
{
if ( year > 9999 || otherValidations == false )
{
//throw new Exception...
}
// year to work with: new DateTime(year, 1, 1);
}
除了编写我自己的自定义数据类型之外,还有其他选择吗?
在大多数情况下,int
都可以正常工作。
这就是DateTime.Year
是什么,这就是DateTime
构造函数所接受的,所以除非你有特殊的原因需要另一种数据类型,整数可能是最容易处理的。
可能是int。接受整个DateTime对象会令人困惑,因为您的方法只需要年份。从这里开始,int是合乎逻辑的选择,因为它是DateTime的类型。年产权。
这在很大程度上取决于你这一年计划做什么。如果您打算多次传递它,创建您的自定义struct
封装一个int可能是一个好主意,因为您不需要多次验证相同的数字。否则,一个普通的旧int
就可以了。
你可以把它包装成不可变的struct
,但基本上它是和int
加上一些限制。
我会说:选择DateTime
,因为您已经定义了可能需要的操作。为什么要重新发明轮子?
年份为整型。但是如果你可以把它改成属性,你可以在set中添加一些验证,如果只是输入一些函数,你可以添加新的函数来验证它。
int year;
public int Year
{
get
{
if (year > 9999)
throw ...
// check other constrains ...
return year;
}
set
{
if (value > 9999)
throw ...
// check other constrains ...
year = value;
}
}
作为函数:
int GetYear(int year)
{
do validation and possibly throw an exception
return year;
}
但是如果你只在一个函数中使用它,就不需要做任何一个,在负责的函数中做你的验证
我会使用int,除非您计划必须处理BC年或非公历年(以及它们之间的转换)。在BC的情况下,您可能需要一个Year结构体,以便通过ToString显示。在非格里高利历的情况下,事情变得更加复杂。
虽然可以使用int
,但最好的方法是实现一个专门的结构体,因为它能更好地表达您的意图:
public struct Year : IEquatable<Year>, IEquatable<DateTime>, IEquatable<int>
{
/// <summary>
///
/// </summary>
/// <param name="year"></param>
/// <exception cref="ArgumentOutOfRangeException">
/// When <see cref="year"/> is not within the range from <value>1</value> to <value>9999</value>.
/// </exception>
public Year(int year)
{
// same limits as DateTime
// be careful when changing this values, because it might break
// conversion from and to DateTime
var min = 1;
var max = 9999;
if (year < min || year > max)
{
var message = string.Format("Year must be between {0} and {1}.", min, max);
throw new ArgumentOutOfRangeException("year", year, message);
}
_value = year;
}
private readonly int _value;
public bool Equals(Year other)
{
return _value == other._value;
}
public bool Equals(DateTime other)
{
return _value == other.Year;
}
public bool Equals(int other)
{
return _value == other;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (obj is Year) return Equals((Year) obj);
if (obj is int) return Equals((int)obj);
if (obj is DateTime) return Equals((DateTime) obj);
return false;
}
public static Year MinValue
{
get
{
return new Year(DateTime.MinValue.Year);
}
}
public static Year MaxValue
{
get
{
return new Year(DateTime.MaxValue.Year);
}
}
public override int GetHashCode()
{
return _value;
}
public static bool operator ==(Year left, Year right)
{
return left.Equals(right);
}
public static bool operator !=(Year left, Year right)
{
return !left.Equals(right);
}
public override string ToString()
{
return _value.ToString();
}
public string ToString(IFormatProvider formatProvider)
{
return _value.ToString(formatProvider);
}
public string ToString(string format)
{
return _value.ToString(format);
}
public string ToString(string format, IFormatProvider formatProvider)
{
return _value.ToString(format, formatProvider);
}
public DateTime ToDateTime()
{
return new DateTime(_value, 1, 1);
}
public int ToInt()
{
return _value;
}
public static implicit operator DateTime(Year year)
{
return new DateTime(year._value, 1, 1);
}
public static explicit operator Year(DateTime dateTime)
{
return new Year(dateTime.Year);
}
public static explicit operator int(Year year)
{
return year._value;
}
/// <summary>
///
/// </summary>
/// <param name="year"></param>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException">
/// When <see cref="year"/> is not within the range from <value>1</value> to <value>9999</value>.
/// </exception>
public static explicit operator Year(int year)
{
return new Year(year);
}
}
写一个自定义数据类型Year
。它比在SO上询问更快:-)您可以将其声明为struct
以接收与使用int
类似的行为,但在类型的逻辑中添加您非常特定的约束。