自定义 ShortDate 类型 (结构: IComparable)






3.24/5 (12投票s)
2005年2月14日
2分钟阅读

63211

101
一个 struct 例子
引言
这是一个自定义的 C# .NET Date
类型 (struct
),可以帮助你处理与 string
之间的转换。 该 struct
实现了 IComparable
接口,并重写了 ToString
, Equals
和 GetHashCode()
函数。
背景
定义一个 struct
几乎和定义一个 class
类似
[attributes] [modifiers] struct <structName> [: interfaces]
{
[struct-body]
}[;]
像 class
一样, struct
可以包含其他类型,有时被称为 class
的轻量级版本,因为在内部 struct
是一个值类型。 创建一个 struct
实例不会导致垃圾回收 (除非构造函数直接或间接地创建一个引用类型实例),而创建一个引用类型实例可能会导致垃圾回收。 关于 struct
的另一件事是它始终有一个内置的 public
默认构造函数,并且没有析构函数。
struct
和 class
有什么不同
struct
是隐式sealed
的,而class
不是struct
不能是abstract
的,而class
可以struct
无法在其构造函数中调用: base()
,而没有显式base
类的class
可以struct
无法扩展另一个class
,而class
可以struct
无法声明protected
成员 (例如字段,嵌套类型),而class
可以struct
无法声明abstract
函数成员,而abstract class
可以struct
无法声明virtual
函数成员,而class
可以struct
无法声明sealed
函数成员,而class
可以struct
无法声明override
函数成员,而class
可以。 此规则的唯一例外是struct
可以覆盖System.Object
的virtual
方法,即Equals()
, 和GetHashCode()
, 以及ToString()
(更多信息请访问 StructsVsClasses)
Struct 代码
Date
struct
看起来像这样
using System;
using System.Text.RegularExpressions;
[Serializable]
public struct Date : IComparable
{
//private members
//public members
//constructor
//functions
//IComparable & overridden implementation
}
我想构建一个包含三个字段的 ShortDate
struct
private UInt16 _day;
private UInt16 _month;
private UInt16 _year;
接下来,我将这些字段设置为 public
,所以现在我的 struct
有三个属性
public UInt16 Day
{
get { return _day; }
set
{
if (value > 31)
{
throw new ArgumentException("Day out of range[31]");
}
else
{
_day = value;
}
}
}
public UInt16 Month
{
get { return _month; }
set
{
if (value > 12)
{
throw new ArgumentException("Month out of range[12]");
}
else
{
_month = value;
}
}
}
public UInt16 Year
{
get { return _year; }
set
{
if (value.ToString().Length > 4)
{
throw new ArgumentException("Year out of range.");
}
else
{
_year = value;
}
}
}
除了使所有字段都等于零的默认构造函数外,我还创建了另一个构造函数,它将使用来自 DateTime
参数的数据填充这些字段
public Date(DateTime dt)
{
_month = Convert.ToUInt16(dt.Month);
_day = Convert.ToUInt16(dt.Day);
_year = Convert.ToUInt16(dt.Year);
}
IComparable
的实现和 ToString
, Equals
和 GetHashCode()
函数的重写
public int CompareTo(object obj)
{
Date dt = (Date) obj;
UInt16 i = 0;
if (dt._day == _day)
{
i += 100;
}
if (dt._month == _month)
{
i += 010;
}
if (dt._year == _year)
{
i += 001;
}
return i;
}
public override bool Equals(object obj)
{
if (obj == null || ! (obj is Date))
return false;
try
{
Date other = (Date)obj;
return this._day == other._day
&& this._month == other._month
&& this._year == other._year;
}
catch
{
return false;
}
}
public override int GetHashCode()
{
return (_day ^ _month ^ _year);
}
public override string ToString()
{
return (_day.ToString() + "/" + _month.ToString() + "/" + _year.ToString());
}
public string ToString(string separator)
{
string s1="", s2="";
if(_day.ToString().Length == 1 )
{
s1="0";
}
if( _month.ToString().Length == 1 )
{
s2="0";
}
return (s1+_day.ToString()+separator+s2+_month.ToString()+separator+_year);
}
public static bool operator >(Date d1,Date d2)
{
if( d1.ToDateTime() > d2.ToDateTime() )
{
return true;
}
return false;
}
public static bool operator <(Date d1,Date d2)
{
if( d1.ToDateTime() < d2.ToDateTime() )
{
return true;
}
return false;
}
最后是一些有用的函数来帮助我们管理这个 Date
类型
public bool IsDateTime(string dt)
{
Regex rgx = new
Regex(@"(?<Day>\d{1,2})/(?<Month>\d{1,2})/(?<Year>(?:\d{4}|\d{2}))");
if (rgx.IsMatch(dt))
{
return true;
}
else
{
return false;
}
}
public DateTime StringToDate(string dt)
{
if (IsDateTime(dt))
{
_day = Convert.ToUInt16(dt.Split('/')[0]);
_month = Convert.ToUInt16(dt.Split('/')[1]);
_year = Convert.ToUInt16(dt.Split('/')[2]);
}
else
{
throw new ArgumentException("The string can't be converted to a date");
}
return new DateTime(Year, Month, Day);
}
public DateTime StringToDate(string dt, char separator)
{
try
{
_day = Convert.ToUInt16(dt.Split(separator)[0]);
_month = Convert.ToUInt16(dt.Split(separator)[1]);
_year = Convert.ToUInt16(dt.Split(separator)[2]);
return new DateTime(Year, Month, Day);
}
catch (Exception)
{
throw new InvalidCastException("The input string is not a date format");
}
}
public DateTime ToDateTime()
{
return new DateTime(Year, Month, Day);
}
public static DateTime ToDateTime(Date dt)
{
return new DateTime(dt.Year, dt.Month, dt.Day);
}
Using the Code
您现在可以将此 struct
包含到项目中并尝试一下,这里有一些例子
private void Page_Load(object sender, System.EventArgs e)
{
//default constructor
Date d1 = new Date();
Response.Write("Luna: "+d1.Month+" Zi: "+d1.Day+" An: "+d1.Year);
//defined constructor
Date d2 = new Date(DateTime.Now);
Response.Write(d2.ToString());
//StringToDate will fill the fields
Date d3 = new Date();
Response.Write(d3.StringToDate("01/02/05"));
Response.Write(d1.ToString()+" -d1- "+ d1.GetHashCode());
Response.Write(d2.ToString()+" -d2- "+ d2.GetHashCode());
Response.Write(d3.ToString()+" -d3- "+ d3.GetHashCode());
Date d4 = new Date();
d4.StringToDate("01/02/05");
Date d5 = new Date();
d5.Day = 1;
d5.Month = 5;
d5.Year = 05;
Response.Write(d4.ToString()+" Equals "+d5.ToString()+
"? "+d4.Equals(d5));
Response.Write(d4.ToString()+" CompareTo "+d5.ToString()+
"? "+d4.CompareTo(d5));
}
历史
- 版本 2.0
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。