DateTime有默认构造函数吗?

简介:

不知道你看到这个题目会不会很郁闷,但这的确是一个很值得考虑的问题。
你当然会说,这有啥,代码运行一下不就知道啦。
 

1 DateTime d  =   new  DateTime();

编译虽然通过,但我们要考虑一下,这个d目前是什么值呢?
这就是一个很很值得考虑的问题。 
我们知道,如果要声明一个DateTime新实例初始化为指定的年、月和日
使用如下的代码
 

1 DateTime d  =   new  DateTime( 2007 , 1 , 1 );

那么,按一般我们对类的设计方法,DateTime的默认构造函数返回当前的日期实例比较合理。
但事实是
 

1  DateTime d  =   new  DateTime();
2  System.Console.WriteLine(d); // 0001-1-1 0:00:00

日期0001-1-1 0:00:00表示的是基督元年
 

1  DateTime d  =   new  DateTime();
2  System.Console.WriteLine(d); // 0001-1-1 0:00:00
3  System.Console.WriteLine(DateTime.MinValue); // 0001-1-1 0:00:00

不过,事情到这里还没有结束,感觉上我们使用DateTime的默认构造函数产生了基督元年,但你去查一下DateTime的帮助,你会吓一跳,文档上根本没有声明过DateTime的默认构造函数。
DateTime的构造函数重载为下表

DateTime (Int64)
DateTime (Int64, DateTimeKind)
DateTime (Int32, Int32, Int32)
DateTime (Int32, Int32, Int32, Calendar)
DateTime (Int32, Int32, Int32, Int32, Int32, Int32)
DateTime (Int32, Int32, Int32, Int32, Int32, Int32, Calendar)
DateTime (Int32, Int32, Int32, Int32, Int32, Int32, DateTimeKind)
DateTime (Int32, Int32, Int32, Int32, Int32, Int32, Int32)
DateTime (Int32, Int32, Int32, Int32, Int32, Int32, Int32, Calendar)
DateTime (Int32, Int32, Int32, Int32, Int32, Int32, Int32, DateTimeKind)
DateTime (Int32, Int32, Int32, Int32, Int32, Int32, Int32, Calendar, DateTimeKind)

的的确确没有默认构造函数,是不是写文档的人不仔细把默认构造函数忘记描述了呢?
当然不是这样的,原因我们来逐步分析
DateTime的定义为:public struct DateTime 
我们看到DateTime不是class,而是我们没有看到过的struct(结构)。
结构是一个和class非常接近的数据类型,我们来演示class和struct的区别
以下是对同一个现象描述的class和struct
struct常用来做一个轻量级的类,快速的分配和快速的销毁,但这同时也失去了继承等能力。所以如果你需要类的所有特性,就还是使用类更好。

1   public   struct  StockStruct
2   {
3
4 public string Name;
5 public string Code;
6 public double In;
7 public double Out;
8 
9 }

10
11   public   class  StockClass
12   {
13 public string Name;
14 public string Code;
15 public double In;
16 public double Out;
17 }


我们分别实例化,代码的运行完全一样
 

1  StockStruct ss  =   new  StockStruct();
2  System.Console.WriteLine(ss.Name);
3  StockClass sc  =   new  StockClass();
4  System.Console.WriteLine(sc.Name);


我们为这两个数据类型添加默认构造函数
 

1   public   struct  StockStruct
2   {
3 /*结构不能包含显式的无参数构造函数 
4 public StockStruct() 
{

5 }
*/
6 public string Name;
7 public string Code;
8 public double In;
9 public double Out;
10
11 }

12
13   public   class  StockClass
14   {
15 public StockClass()
16 {
17 }

18
19 public string Name;
20 public string Code;
21 public double In;
22 public double Out;
23 }


我们发现不能为struct添加显式的无参数构造函数,这是为什么呢?简单的说,你可以这样理解:
class默认没有构造函数,当你一个构造函数都不写得时候,编译器会给你的类添加一个默认的构造函数。
struct天生有一个默认构造函数,该构造函数是由编译器统一控制,所以你就不能再为结构编写默认构造函数了。
我们再次修改我们的代码
 

1   public   struct  StockStruct
2   {
3 public StockStruct(string name,string code)
4 {
5 Name = name;
6 Code = code;
7 }

8 public string Name;
9 public string Code;
10 public double In;
11 public double Out;
12
13 }

14
15   public   class  StockClass
16   {
17 public StockClass(string name, string code)
18 {
19 Name = name;
20 Code = code;
21 }

22
23 public string Name;
24 public string Code;
25 public double In;
26 public double Out;
27 }


以上代码看似没有什么错误,但编译的结构再次让你感到沮丧。
class的代码被编译通过了,struct又有错误了
在控制离开构造函数之前,字段“StockStruct.In”必须完全赋值
在控制离开构造函数之前,字段“StockStruct.Out”必须完全赋值
该错误提示告诉我们,要么我们不给struct编写构造函数,编译器使用各数据类型的默认值,如果我们编写了构造函数,就必须在构造函数中为该struct的所有数据成员完全赋值。
这其实就是值类型和引用类型的一个区别:
值类型,要求在编译时知道对象的大小,引用类型可以推迟到运行时才知道对象的大小。
struct是值类型,因此又推导出另一个特征:struct没有析构函数。
 

1   public   struct  StockStruct : Object
2   {
3 public StockStruct(string name,string code)
4 {
5 Name = name;
6 Code = code;
7 In = 0;
8 Out = 0;
9 }

10 public string Name;
11 public string Code;
12 public double In;
13 public double Out;
14
15 }

16
17   public   struct  HKStock : StockStruct
18  
19 
20 }


上面的代码又错了,struct要求不能从其他类或结构继承,其他结构和类也不允许继承结构(结构天然的就是一个密封类型)。同时推导:struct 不能为 abstract,而应始终为隐式 sealed。
不过,结构仅可以支持接口,所以同时推导:结构成员无法声明为protected。
 

1   public   struct  StockStruct : System.IComparable
2   {
3 public StockStruct(string name, string code)
4 {
5 Name = name;
6 Code = code;
7 In = 0;
8 Out = 0;
9 }

10 public string Name;
11 public string Code;
12 public double In;
13 public double Out;
14
15
16 public int CompareTo(object obj)
17 {
18 return -1;
19 }

20
21 }


结构可以包含构造函数、常量、字段、方法、属性、索引器、运算符、事件和嵌套类型,但如果同时需要上述几种成员,则应当考虑改为使用类作为类型。因为


本文转自shyleoking 51CTO博客,原文链接:http://blog.51cto.com/shyleoking/806257


相关文章
|
2天前
|
弹性计算 运维 搜索推荐
三翼鸟携手阿里云ECS g9i:智慧家庭场景的效能革命与未来生活新范式
三翼鸟是海尔智家旗下全球首个智慧家庭场景品牌,致力于提供覆盖衣、食、住、娱的一站式全场景解决方案。截至2025年,服务近1亿家庭,连接设备超5000万台。面对高并发、低延迟与稳定性挑战,全面升级为阿里云ECS g9i实例,实现连接能力提升40%、故障率下降90%、响应速度提升至120ms以内,成本降低20%,推动智慧家庭体验全面跃迁。
|
3天前
|
数据采集 人工智能 自然语言处理
3分钟采集134篇AI文章!深度解析如何通过云无影AgentBay实现25倍并发 + LlamaIndex智能推荐
结合阿里云无影 AgentBay 云端并发采集与 LlamaIndex 智能分析,3分钟高效抓取134篇 AI Agent 文章,实现 AI 推荐、智能问答与知识沉淀,打造从数据获取到价值提炼的完整闭环。
351 91
|
10天前
|
人工智能 自然语言处理 前端开发
Qoder全栈开发实战指南:开启AI驱动的下一代编程范式
Qoder是阿里巴巴于2025年发布的AI编程平台,首创“智能代理式编程”,支持自然语言驱动的全栈开发。通过仓库级理解、多智能体协同与云端沙箱执行,实现从需求到上线的端到端自动化,大幅提升研发效率,重塑程序员角色,引领AI原生开发新范式。
851 156
|
3天前
|
数据采集 缓存 数据可视化
Android 无侵入式数据采集:从手动埋点到字节码插桩的演进之路
本文深入探讨Android无侵入式埋点技术,通过AOP与字节码插桩(如ASM)实现数据采集自动化,彻底解耦业务代码与埋点逻辑。涵盖页面浏览、点击事件自动追踪及注解驱动的半自动化方案,提升数据质量与研发效率,助力团队迈向高效、稳定的智能化埋点体系。(238字)
257 156
|
4天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
11天前
|
机器人 API 调度
基于 DMS Dify+Notebook+Airflow 实现 Agent 的一站式开发
本文提出“DMS Dify + Notebook + Airflow”三位一体架构,解决 Dify 在代码执行与定时调度上的局限。通过 Notebook 扩展 Python 环境,Airflow实现任务调度,构建可扩展、可运维的企业级智能 Agent 系统,提升大模型应用的工程化能力。
|
人工智能 前端开发 API
前端接入通义千问(Qwen)API:5 分钟实现你的 AI 问答助手
本文介绍如何在5分钟内通过前端接入通义千问(Qwen)API,快速打造一个AI问答助手。涵盖API配置、界面设计、流式响应、历史管理、错误重试等核心功能,并提供安全与性能优化建议,助你轻松集成智能对话能力到前端应用中。
816 154