1.命名空间
(1)命名空间基本概念
概念
命名空间是用来组织和重用代码的
作用
就像是一个工具包 类就像是一件一件的工具 都是申明在命名空间中的
(2)命名空间的使用
// 基本语法
// namespace 命名空间名
// {
// 类
// 类
// }
namespace MyGame
{
class GameObject
{
}
}
namespace MyGame
{
class Player : GameObject
{
}
}
(3)不同命名空间中允许有同名类
namespace MyGame2
{
// 在不同的命名空间中是可以由同名类的
class GameObject
{
}
}
(4)命名空间可以包裹命名空间
namespace MyGame
{
namespace UI
{
class Image
{
}
}
namespace Game
{
class Image
{
}
}
}
(5)关于修饰类的访问修饰符
public --命名空间中的类默认为 public
internal --只能在该程序集中使用
abstract --抽象类
sealed --密封类
partial-- 分部类
(6)不同命名空间中相互使用 需要引用命名空间或指明出处
GameObject g = new GameObject();
Image img0 = new Image();
MyGame.UI.Image img = new MyGame.UI.Image();
MyGame.Game.Image img2 = new MyGame.Game.Image();
2.万物之父中的方法
(1)静态方法
// 静态方法 Equals 判断两个对象是否相等
// 最终的判断权交给左侧对象的 Equals 方法
// 不管值类型引用类型都会按照左侧对象 Equals 方法的规则来进行比较
Console.WriteLine(Object.Equals(1, 1));
// Test t = new Test();
// Test t2 = new Test();
// Console.WriteLine(Object.Equals(t, t2));
// 静态方法 ReferenceEquals
// 比较两个对象是否是相同的引用 主要是用来比较引用类型的对象
// 值类型对象返回值始终是 false
// Console.WriteLine(Object.ReferenceEquals(t, t2));
(2)成员方法
// 普通方法 GetType
// 该方法在反射相关知识点是非常重要的方法 之后我们会具体的讲解这里返回的 Type 类型
// 该方法的主要作用就是获取对象运行时的类型 Type
// 通过 Type 结合反射相关知识点可以做很多关于对象的操作
Test t = new Test();
Type type = t.GetType();
// 普通方法 MemberwiseClone
// 该方法用于获取对象的浅拷贝 口语化的意思就是会返回一个新的对象
// 但是新对象中的引用变量会和老对象中一致
Test t2 = t.Clone();
Console.WriteLine("克隆对象后");
Console.WriteLine("t.i = " + t.i);
Console.WriteLine("t.t2.i = " + t.t2.i);
Console.WriteLine("t2.i = " + t2.i);
Console.WriteLine("t2.t2.i = " + t2.t2.i);
t2.i = 20;
t2.t2.i = 21;
Console.WriteLine("改变克隆体信息后");
Console.WriteLine("t.i = " + t.i);
Console.WriteLine("t.t2.i = " + t.t2.i);
Console.WriteLine("t2.i = " + t2.i);
Console.WriteLine("t2.t2.i = " + t2.t2.i);
(3)虚方法
// 虚方法 Equals
// 默认实现还是比较两者是否为同一个引用 即相当于 ReferenceEquals
// 但是微软在所有值类型的基类 System.ValueType 中重写了该方法 用来比较值相等
// 我们也可以重写该方法 定义自己的比较相等的规则
// 虚方法 GetHashCode
// 该方法是获取对象的哈希码
// (一种通过算法算出的 表示对象的唯一编码 不同哈希码有可能一样 具体情况根据哈希算法决定)
// 我们可以通过重写该函数来自己定义对象的哈希码算法 正常情况下我们使用的极少基本不用
// 虚方法 ToString
// 该方法用于返回当前对象代表的字符串 我们可以重写它定义我们自己的对象转字符串规则
// 该方法非常常用当我们调用打印方法时 默认使用的就是对象的 ToString 方法后打印出来的内容
Console.WriteLine(t);
3.string
(1)字符串指定位置获取
// 字符串本质是 char 数组
string str = "唐老狮";
Console.WriteLine(str[0]);
// 转为 char 数组
char[] chars = str.ToCharArray();
Console.WriteLine(chars[1]);
for (int i = 0; i < str.Length; i++)
{
Console.WriteLine(str[i]);
}
(2)字符串拼接
str = string.Format("{0}{1}", 1, 3333);
Console.WriteLine(str);
(3)正向查找字符位置
str = "我是唐老狮!";
int index = str.IndexOf("唐");
Console.WriteLine(index);
index = str.IndexOf("吊");
Console.WriteLine(index);
(4)反向查找指定字符串位置
str = "我是唐老狮唐老狮";
index = str.LastIndexOf("唐老狮");
Console.WriteLine(index);
index = str.LastIndexOf("唐老师");
Console.WriteLine(index);
(5)移除指定位置后的字符
str = "我是唐老狮唐老狮";
str.Remove(4);
Console.WriteLine(str);
str = str.Remove(4);
Console.WriteLine(str);
// 执行两个参数进行移除
// 参数1 开始位置
// 参数2 字符个数
str = str.Remove(1, 1);
Console.WriteLine(str);
(6)替换指定字符串
str = "我是唐老狮唐老狮";
str.Replace("唐老狮", "老炮儿");
Console.WriteLine(str);
str = str.Replace("唐老狮", "老炮儿");
Console.WriteLine(str);
(7)大小写转换
str = "ksdfasdfasfasdfsasdfasdf";
str.ToUpper();
Console.WriteLine(str);
str = str.ToUpper();
Console.WriteLine(str);
str.ToLower();
Console.WriteLine(str);
str = str.ToLower();
Console.WriteLine(str);
(8)字符串截取
str = "唐老狮唐老狮";
// 截取从指定位置开始之后的字符串
str.Substring(2);
Console.WriteLine(str);
str = str.Substring(2);
Console.WriteLine(str);
// 参数一 开始位置
// 参数二 指定个数
// 不会自动的帮助你判断是否越界 你需要自己去判断
str = str.Substring(2, 2);
Console.WriteLine(str);
(9)字符串切割
str = "1_1|2_2|3_3|5_1|6_1|7_2|8_3";
string[] strs = str.Split('|');
for (int i = 0; i < strs.Length; i++)
{
Console.WriteLine(strs[i]);
}
4.StringBuilder
C# 提供的一个用于处理字符串的公共类
主要解决的问题是:
修改字符串而不创建新的对象 需要频繁修改和拼接的字符串 可以使用它 可以提高性能
使用前需要引用命名空间
(1)初始化直接指明内容
StringBuilder str = new StringBuilder("123123123");
Console.WriteLine(str);
(2)容量
// StringBuider 存在一个内存容量的问题 每次往里面增加时会自动扩容
// 获得容量
Console.WriteLine(str.Capacity);
// 获得字符长度
Console.WriteLine(str.Length);
(3)增删查改替换
// 增
str.Append("4444");
Console.WriteLine(str);
Console.WriteLine(str.Length);
Console.WriteLine(str.Capacity);
str.AppendFormat("{0}{1}",100,999);
Console.WriteLine(str);
Console.WriteLine(str.Length);
Console.WriteLine(str.Capacity);
// 插入
str.Insert(0, "唐老狮");
Console.WriteLine(str);
// 删
str.Remove(0, 10);
Console.WriteLine(str);
// 清空
// str.Clear();
// Console.WriteLine(str);
// 查
Console.WriteLine(str[1]);
// 改
str[0] = 'A';
Console.WriteLine(str);
// 替换
str.Replace("1", "唐");
Console.WriteLine(str);
// 重新赋值 StringBuilder
str.Clear();
str.Append("123123");
Console.WriteLine(str);
// 判断 StringBuilder 是否和某一个字符串相等
if (str.Equals("12312"))
{
Console.WriteLine("相等");
}
5.结构体和类的区别
结构体和类最大的区别是在存储空间上的 因为结构体是值 类是引用
因此他们的存储位置一个在栈上一个在堆上
通过之前知识点的学习 我相信你能够从此处看出他们在使用上的区别 --值和引用对象在赋值时的区别
结构体和类在使用上很类似 结构体甚至可以用面向对象的思想来形容一类对象
结构体具备着面向对象思想中封装的特性 但是它不具备继承和多态的特性 因此大大减少了他的使用频率
由于结构体不具备继承的特性所以他不能够用 protected 保护访问修饰符
1.结构体是值类型 类是引用类型
2.结构体存在栈中 类存在堆中
3.结构体成员不能使用 protected 访问修饰符 而类可以
4.结构体成员变量申明不能指定初始值 而类可以
5.结构体不能申明无参的构造函数 而类可以
6.结构体申明有参构造函数后 无参构造不会被顶掉
7.结构体不能申明析构函数 而类可以
8.结构体不能被继承 而类可以
9.结构体需要在构造函数中初始化所有成员变量 而类随意
10.结构体不能被静态 static 修饰(不存在静态结构体) 而类可以
11.结构体不能在内部申明和自己一样的结构体变量 而类可以
结构体可以继承接口 因为接口是行为的抽象
1.想要用继承和多态时 直接淘汰结构体 比如玩家 怪物等等
2.对象是数据集合时 优先考虑结构体 比如位置 坐标等等
3.从值类型和引用类型赋值时的区别上去考虑 比如经常被赋值传递的对象 并且改变赋值对象 原对象不想跟着变化时 就用结构体 比如坐标 向量 旋转等等
6.抽象类和接口的区别
(1)知识回顾
抽象类和抽象方法
abstract 修饰的类和方法
抽象类不能被实例化
抽象方法只能在抽象类中申明 是个纯虚方法 必须在子类实现
接口
interface 自定义类型
是行为的抽象
不包含成员变量
仅包含方法 属性 索引器 事件 成员都不能实现 建议不写访问修饰符 默认 public
(2)概念
1.都可以被继承
2.都不能直接初始化
3.都可以包含方法申明
4.子类必须实现未实现的方法
5.都遵循里氏替换原则
区别
1.抽象类中可以有构造函数 接口中不能
2.抽象类只能被单一继承 接口可以被继承多个
3.抽象类中可以有成员变量 接口中不能
4.抽象类中可以申明成员方法 虚方法 抽象方法 静态方法 接口中只能申明没有实现的抽象方法
5.抽象类方法可以使用访问修饰符 接口中建议不写 默认 public
表示对象的用抽象类 表示行为拓展的用接口
不同对象拥有的共同行为 我们往往可以使用接口来实现
举个例子:
动物是一类对象 我们自然会选择抽象类 而飞翔是一个行为 我们自然会选择接口