C#中进行类型转换,可以有这样的写法:
int.Parse("23");
Parse()是一个方法,但Parse()究竟是谁的方法?F12转到定义,结果我们就看到了:
public readonly struct Int32 : IComparable, IComparable<int>, IConvertible, IEquatable<int>, IFormattable { public static int Parse(string s)
这什么意思?我们看到了Parse()是Int32的一个静态方法。而Int32又是什么?它是一个
结构(struct)是一个和类(class)非常非常相似的封装容器。它的成员和语法,和类几乎一模一样。除了上面的静态方法调用,还可以:
//new一个结构实例,生成它的实例对象 int age = new Int32(); //调用结构的实例方法 age.CompareTo(21);
但是,结构
我们可以自己创建一个结构,
#试一试#
internal struct Bed //源栈同学的床位 { //public Bed(){} //报错 //报错:没有给_id赋值 //public Bed(string room) //{ // Room = room; //} private int _id; internal string Room { get; set; } public bool HasBooked; }
结构是值类型。(class是引用类型)
所以结构类型的变量是不能被赋值为null(空地址)的:
Bed bed = null; //报错的
此外,下面的代码可以帮助你理解值类型和引用类型的区别:(对比Bed分别为struct和class)
Bed bed /*= new Bed()*/; //bed没有指向任何对象 bed.HasBooked = true; //但bed.HasBooked可以直接被赋值,为什么?如果Bed不是struct而是class的话,这样的代码是会报错(编译时或运行时)的。因为引用类型变量bed,只能存放对象地址,无法存放HasBooked的值。
但当dream是struct的时候,dream本身是有“结构”的,存放HasBooked的位置是预留着的,所以可以赋值。
虽然因为结构是值类型,直接存放在栈中,可以快速读取;但它的数据量不能太大,否则就会:
引用类型的优劣正好相反:节约栈空间;只赋值地址不copy内容,传递时更快……
但我们一般不使用struct,因为:
包括日期(年月日)和时间(小时分钟秒等)。.NET为我们提供了大量关于日期的属性和方法,以方便我们的开发。
演示F12查看metadata:……
1)构造函数:通过new DateTime()构造一个时间对象,可以指定年月日小时分钟秒等:
//2019年12月1日 DateTime date = new DateTime(2019, 12, 1); //2019年12月1日 19点52分24秒 DateTime dateTime = new DateTime(2019, 12, 1, 19, 52, 24);
2)静态属性:DateTime.Now,获取当前时间
Console.WriteLine(DateTime.Now);3)实例属性:根据时间变量取得它的年月日(Day/Year/Month)等,通常和DateTime.Now搭配使用:
Console.WriteLine(DateTime.Now.Day); //当月的第几日
4)实例方法:在现有时间基础上增减,比如AddDays()/AddMonths()/AddYears()……
5)ToString()方法:可以用于指定日期显示的格式。通常,我们使用字符串指定。用y代表year,用M(注意大写)代表month,用d代表day等,如下所示:
Console.WriteLine(DateTime.Now.ToString( "yyyy年MM月dd日 hh点mm分ss秒")); //显示:2019年12月01日 07点59分14秒
另外,注意DateTime中已经出现了:
它也是一个struct,表示的是一段时间。注意:
TimeSpan span = new TimeSpan(2, 4, 12, 30, 0); Console.WriteLine(span.Hours); Console.WriteLine(span.TotalHours);
阅读源代码的时候,我们还发现了这样的代码:
public static DateTime operator +(DateTime d, TimeSpan t);
这被称之为运算符重载。实际上就是改变了运算符加号(+)的运算逻辑:本来加号是只能用于数值型类型的,DateTime显然不是数值,本是不应该能够使用加号的,但重载之后:
Console.WriteLine(DateTime.Now + new TimeSpan(5000));
这就是因为在DateTime类中,进行了上述运算符重载。
任何一个类都可以进行运算符重载,比如我们的Student类:
public static Student operator +(Student student, int age) { student.Age += age; return student; }然后,才可以将Student对象和+并用:
Student student = new Student { Age = 17}; student = student + 1; Console.WriteLine(student.Age);
其语法要求是:
PS:不是所有运算符都可以重载。具体可查看:可以重载的运算符
运算符重载是一种非常强大的语法,在.NET基本类库中大量的使用!极大的方便了开发人员,优雅了代码!
所以,DateTime和TimeSpan,可以使用:
和运算符重载非常类似,但额外的引入了隐式(implicit)和显式(explicit)两个关键字:
public static implicit /*explicit*/ operator Student(Bed bed) { return new Student { Bed = bed }; }
类型之间的转换,本来只能发生在“相关”(比如数值、继承关系)类型之间。如果没有类型转换重载,这样的代码是不行的:
Student student = /*(Student)*/new Bed();
类型转换重载也主要应用于.NET的基础类库中,比如:
public static implicit operator ReadOnlySpan<char>(string? value)
复习:J&C:Object / hash值 / equals() / toString() / 装箱拆箱
object是Object的别名/简写。
简单解释一下:
会判断两个对象是不是值类型:(演示:网站查看源代码)
public /*class*/ struct Bed //源栈同学的床位 { public int Id;
如果是值类型,比较两个对象的值内容(所有字段)相同为true,否则为false
Bed dream = new Bed(); dream.Id = 10; Bed sleep = new Bed(); sleep.Id = 10; Console.WriteLine(Object.Equals(dream, sleep));
演示:当Bed为class时的结果
struct定义的值类型,默认是不支持使用==的。能使用的(比如DateTime),都是因为进行了==的运算符重载!或者本身是数值类型(比如int)或enum。
演示报错:
Console.WriteLine(dream == sleep);
public static bool operator ==(Bed bed1, Bed bed2) { return bed1.Id == bed2.Id;PS:重载==之后会要求(警告)override Equals()
== 作用于引用类型,同Equals()方法,就比较是否指向同一个对象(除非进行了运算符重载,比如string)
复习:J&C:字符串:值类型?/ 池 / 常用方法 / StringBuilder / 正则
string是String的别名/简写。
String中重写了运算符==,所以不需要(像Java一样)使用Equals()方法
Console.WriteLine(name == "阿泰");
演示(复习)常用属性方法
Console.WriteLine(welcome[0]);
if (name == string.Empty)
string.IsNullOrEmpty(welcome); string.IsNullOrWhiteSpace(name);
Console.WriteLine(name.Contains('阿'));
double pai = 3.1415; Console.WriteLine(string.Format("圆周率为:{0:0.00}……", pai));但现在更多的是使用内插,上述格式同样适用:
Console.WriteLine($"一起帮·源栈{pai:0.00}");
说明:学习这个类型,完全是为了面试需要。^_^
很多时候,dynamic完全和object完全一致,任何类型变量都可以使用dynamic声明。使用dynamic标记的变量可以绕过C#的编译时(注意:仅仅是编译时)的类型检查。
object o = "986"; Console.WriteLine(o - 88); //编译时错误 dynamic d = "986"; Console.WriteLine(d - 98); //绕过了类型检查
但是,dynamic并不意味这变量类型可变,当我们运行d-98时会报出因类型不匹配造成的错误:
#常见面试题:var、object和dynamic的区别#
多快好省!前端后端,线上线下,名师精讲
更多了解 加: