2011-12-02 42 views
12

我在写一个接受年份作为参数的方法。即四位数字等于或小于当年。日历只有格里高利(现在...不知道未来),我肯定不会需要任何东西BC。多年的参数类型

我要使用哪种数据类型?显而易见的解决方案将使用日期时间或的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); 
} 

从写我自己的自定义数据类型相隔一年的任何其他的选择吗?

+2

取决于你用它以后做什么,什么在呼唤它。你是否将它作为一个接口公开?来源从哪里来?如果你只是在比较它,你可能只需要一个Int16。 –

+4

让我们不要发明一个轮子,我会建议保持简单并使用内置的'int'数据类型 – sll

+3

年*在什么日历*?格利高里?希伯来语?回历?不同的用户在不同地点使用不同的日历系统;如果你希望你的软件能够被所有人使用,你可能需要做一些研究。 –

回答

26

在大多数情况下,int会正常工作。

这就是DateTime.Year,这就是DateTime构造函数接收的内容,所以除非你有特定的原因需要另一种数据类型,否则整数可能是最简单的工作。

+4

我最喜欢这个,因为这是最简单的方法(比创建一个特殊的对象来保存Years更简单),它不会让用户有机会认为DateTime的其他组件相关。 – deepee1

+1

+1使用与BCL相同的类型。 – DaveShaw

3

您可以将其封装到不可变的struct中,但基本上它有int有一些限制。

1

我会说:去找DateTime,因为您已经定义了您可能需要的操作。为什么重新发明轮子?

4

可能是int。接受整个DateTime对象会令人困惑,因为你的方法只需要一年。从那里,int是合乎逻辑的选择,因为它是DateTime.Year属性的类型。

0

是否写入自定义数据类型Year。这比在这里询问SO更快:-)您可以声明它为struct以接收类似的行为,例如使用int时,但在类型的逻辑中添加非常特定的约束。

4

这很大程度上取决于您打算如何处理这一年。如果你打算把它传递给很多人,那么创建封装int的自定义struct可能是个好主意,因为你不需要多次验证相同的数字。否则,一个普通的旧int将工作得很好。

1

年份为int。但如果你可以改变它的属性,你可以在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; 
} 

但如果你只是在一个函数中使用它没有必要做任何人,做你的验证负责任的功能。

1

我会使用int,除非您打算必须处理BC或非格里高利年(与他们之间的转换)。在BC情况下,您可能需要通过ToString为显示目的使用Year结构。在非格利高里的情况下,情况变得更加复杂。

1

虽然可以使用一个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); 
    } 
}