2011-12-02 40 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); 
    } 
}