——值类型和引用类型
区别:
- 值类型和引用类型在内存上存储的地方不一样。
- 值类型的值是存储在内存的栈当中。
- 引用类型的值是存储在内存的堆中。
- 在传递值类型和传递引用类型的时候,传递的方式不一样。
值类型我们称之为值传递,引用类型我们称之为引用传递。
常见的值类型:int、double、bool、char、decimal、struct、enum
常见的引用类型:string、自定义类、数组、、、、、、
给一张图帮助理解
引用类型的变量名存的是值所在堆内存的地址,而值类型是在栈内存中存的本身
——字符串
- 字符串的重要特性——不可变性
- 当你给一个字符串重新赋值之后,老值并没有销毁,而是重新开辟一块空间存储新值。
- 当程序结束后,GC扫描整个内存,如果发现有的空间没有被指向,则立即把它销毁。
- 我们可以讲字符串看做是char类型的一个只读数组。
- ToCharArray();将字符串转换为char数组
- new string(char[] chs):能够将char数组转换为字符串
//可以讲string类型 看做是char类型的一个只读数组
string s = "abcdefg";
s = "bbcdefg";// s[0] = 'b';不能这样做因为是只读的数组
char[] chs = s.ToCharArray();//首先将字符串转换为char类型的数组
chs[0] = 'b'; //将字符数组转换为我们的字符串
s = new string(chs);
Console.WriteLine(s[0]);
Console.WriteLine(s);
- 字符串提供的各种方法
- Length属性:获得当前字符串中字符的个数
- ToUpper():将字符转换成大写形式
- ToLower():将字符串转换成小写形式
- Equals(stringTwo,StringComparison.OrdinalIgnoreCase):比较两个字符串,可以忽略大小写
- Split(“分隔标识”,[StringSplitOptions.RemoveEmptyEntries]):分割字符串,返回字符串类型的数组,按照空格分隔之后,空格会出现在返回的数组中,第二个参数就是取消空格的
- Substring(开始位置,截取数量):截取字符串。
- IndexOf(“查找的字符”,[开始位置]):判断某个字符串在字符串中第一次出现的位置,如果没有返回-1,
- LastIndexOf():判断某个字符串在字符串中最后一次出现的位置
- StartsWith():判断以….开始
- EndsWith():判断以…结束
- Replace(“字符串”,“替换成字符串”):将字符串中某个字符串替换成一个新的字符串
- Contains():判断某个字符串是否包含指定的字符串
- Trim():去掉字符串中前后的空格
- TrimEnd():去掉字符串中结尾的空格
- TrimStart():去掉字符串中前面的空格
- string.IsNullOrEmpty():判断一个字符串是否为空或者为null
- string.Join(“指定字符串”,数组):将数组按照指定的字符串连接,返回一个字符串。
//从Email中提取出用户名和域名
string email = "285014478@qq.com";
int index = email.IndexOf('@');
string userName = email.Substring(0, index);
string yuMing = email.Substring(index+1);
Console.WriteLine(yuMing);
Console.WriteLine(userName);
——继承
我们可能会在一些类中,写一些重复的成员,我们可以将这些重复的成员,单独的封装到一个类中,作为这些类的父类。
子类继承了父类,那么子类从父类那里继承过来了什么?
- 首先,子类继承了父类的属性和方法,但是子类并没有继承父类的私有字段。
- 子类并没有继承父类的构造函数,但是。子类会默认的调用父类无参数的构造函数,来创建父类对象,让子类可以使用父类中的成员。所以,如果在父类中重新写了一个有参数的构造函数之后,那个无参数的就被干掉了,子类就调用不到了,所以子类会报错。
- 解决办法:
- 在父类中重新写一个无参数的构造函数
- 在子类中显示的调用父类的构造函数,让子类别去调用无参的构造函数,使用关键字:base()
- 解决办法:
继承的特性
- 继承的单根性:一个子类只能有一个父类。
- 继承的传递性
来个例子总结一下
//Main方法中调用
static void Main(string[] args)
{
//记者:我是记者 我的爱好是偷拍 我的年龄是34 我是一个男狗仔
//程序员:我叫孙全 我的年龄是23 我是男生 我的工作年限是 3年
Reporter rep = new Reporter("狗仔", 34, '男', "偷拍");
rep.ReporterSayHello();
Programmer pro = new Programmer("程序猿", 23, '男', 3);
pro.ProgrammerSayHello();
Console.ReadKey();
}
//父类
public class Person
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private int _age;
public int Age
{
get { return _age; }
set { _age = value; }
}
private char _gender;
public char Gender
{
get { return _gender; }
set { _gender = value; }
}
//父类构造函数
public Person(string name, int age, char gender)
{
this.Name = name;
this.Age = age;
this.Gender = gender;
}
}
//记者类
//:Person继承自Person
public class Reporter : Person
{
//显示的调用父类的构造函数
public Reporter(string name, int age, char gender, string hobby): base(name, age, gender)
{
this.Hobby = hobby;//自己独有的属性
}
private string _hobby;
public string Hobby
{
get { return _hobby; }
set { _hobby = value; }
}
public void ReporterSayHello()
{
Console.WriteLine("我叫{0},我是一名狗仔,我的爱好是{1},我是{2}生,我今年{3}岁了",this.Name,this.Hobby,this.Gender,this.Age);
}
}
//程序员类
public class Programmer : Person
{
private int _workYear;
public int WorkYear
{
get { return _workYear; }
set { _workYear = value; }
}
public void ProgrammerSayHello()
{
Console.WriteLine("我叫{0},我是一名程序猿,我是{1}生,我今年{2}岁了,我的工作年限是{3}年",this.Name,this.Gender,this.Age,this.WorkYear);
}
public Programmer(string name, int age, char gender, int workYear)
: base(name, age, gender)
{
this.WorkYear = workYear;
}
}