详细语法这点见OO,我必须知道的C#我必须知道的C# - yeyuotc
这里简单陈述
继承
复用父类让子类的代码更简洁,专注于子类扩展自己的东西
//继承: 复用,隐藏,扩展
//复用,父类声明隐藏子类,扩展子类,不用每次都改父类
//覆写 父类中virtual和子类中override
//不想扩展可以使用 sealed
//使用: 复用类很多东西都适用把公共的代码提取出来
//想要类更适配就把基类写成泛型类
//模板配合泛型也是继承
// 接口继承与类的继承区别
// 继承有子类继承父类的关系在,属于IS-A的关系,狗是一种动物,属于的关系
// 接口是包含关系,不能说狗包含动物,什么时候是?我有一个手/我有一个头是包含关系
// 左手和右手就是接口的一个类
// 不能继承两个类的原因,一个类是有界门纲目科属种的
//不能一次同时属于两个类,这是禁止的,但是接口可以
//接口可以像是unity的组件,可以通过不同的接口组成不同的类
//对类可以通过 is来判断有没有这个接口,动态的判断有没有接口
//面向接口编程,面向的是抽象接口,IHand可以是左右手是一个具体的,但我们并不需要
// abstract 很严格的定义,所以函数必须不能实现
//子类中必须实现,很抽象的,一个类只定义方法
//没办法直接创建实例
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
#region //继承
//继承: 复用,隐藏,扩展
//复用,父类声明隐藏子类,扩展子类,不用每次都改父类
//覆写 父类中virtual和子类中override
//不想扩展可以使用 sealed
//使用: 复用类很多东西都适用把公共的代码提取出来
//想要类更适配就把基类写成泛型类
//模板配合泛型也是继承
class ParentClass
{
string name; //父类钟定义的方法和属性
virtual public void Do() { } //密封时候不可以使用virtual
}
//基类
class ChildClass : ParentClass
{
//子类钟新定义的方法和属性,把前面的父类直接复用过来
override public void Do() { }
}
class Example
{
void example()
{
ChildClass child = new ChildClass(); //按人眼,前面是一个child 后面也是child 就可以用到child的东西
ParentClass parent = new ChildClass();//按人眼,前面是一个parent,对我们来说是一个parent但不知道指向的是一个child
}
//隐藏的效果
void File1()
{
ParentClass parent = new ChildClass();
}
void File2()
{
ParentClass parent; //对于第二个文件来说并不知道指向Childclass
//不需要知道child
}
}
#endregion
// 接口继承与类的继承区别
// 继承有子类继承父类的关系在,属于IS-A的关系,狗是一种动物,属于的关系
// 接口是包含关系,不能说狗包含动物,什么时候是?我有一个手/我有一个头是包含关系
// 左手和右手就是接口的一个类
interface IHand{}
interface Ileg { }
class LeftHand : IHand { } //这里是扩展
//不这样 class Man:LeftHand{}
//而是这样:
class Man : IHand //但是人和手是包含的关系,就是表示的关系不同C#做了区别
{}
class A { };
class B { };
// 不能继承两个类的原因,一个类是有界门纲目科属种的
//不能一次同时属于两个类,这是禁止的,但是接口可以
//接口可以像是unity的组件,可以通过不同的接口组成不同的类
//对类可以通过 is来判断有没有这个接口,动态的判断有没有接口
//面向接口编程,面向的是抽象接口,IHand可以是左右手是一个具体的,但我们并不需要
class C : A //, B
{
bool Is_haveinterface()
{
Man man = new Man();
return (man is IHand);
}
}
// abstract 很严格的定义,所以函数必须不能实现
//子类中必须实现,很抽象的,一个类只定义方法
//没办法直接创建实例
C#类型系统
类型系统
//Type
//变量的大小,储存的布局,执行的操作都是由类型决定
// int +/- char struct(复杂)
//定义了规则,使用类型系统/操作系统一样,内置在编程语言中提供规则
//怎么获取数据类型?
C#是一个 编译期的语言,静态语言,很多信息在编译时知道
一个变量的类型在编译时知道
由类型系统进行编码,把int放入操作系统
通用类型(generic type)
var,object,dynamic,template
强类型,静态类型:在编译时候已经知道他是一个什么样的类了
强绑定 var,object是强类型,虽然什么类型都能赋值给它,但是在编译时就知道
object 万能类型,也可以被后面的类型传过去,相当于把被赋值对象的值类型抹去了
泛型也叫模板 template
我这类就写一次,通过传入不同类型的参数来生成其它的类,但是这个类的代码和原来的一样
想想jiangly的线段树模板,不同的签名,仍是静态类型,在编译期确定
dynamic是动态类型
只有当代码执行到这里才知道这里的类型,运行时确定
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//类型系统
//Type
//变量的大小,储存的布局,执行的操作都是由类型决定
// int +/- char struct(复杂)
//定义了规则,使用类型系统/操作系统一样,内置在编程语言中提供规则
//怎么获取数据类型?
/*
C#是一个 编译期的语言,静态语言,很多信息在编译时知道
一个变量的类型在编译时知道
由类型系统进行编码,把int放入操作系统
*/
/*
通用类型(generic type)
var,object,dynamic,template
强类型,静态类型:在编译时候已经知道他是一个什么样的类了
强绑定 ,var,object是强类型,虽然什么类型都能赋值给它,但是在编译时就知道
object 万能类型,也可以被后面的类型传过去,相当于把被赋值对象的值类型抹去了
泛型也叫模板 template
我这类就写一次,通过传入不同类型的参数来生成其它的类,但是这个类的代码和原来的一样
想想jiangly的线段树模板,不同的签名,仍是静态类型,在编译期确定
dynamic是动态类型
只有当代码执行到这里才知道这里的类型,运行时确定
*/
class Animal<T> //任意的类型,吃不同类型的生物应该是不同的生物,复用不同代码
{
T food;
}
class Example2
{
void example()
{
int a = 1;
Type type=a.GetType();//类型本身也可以当变量来用,两个操作互补
int b=(int)Activator.CreateInstance(type);//用法用类型创建一个实例
//大量使用通用类型,只能通过实时的获取类型的信息才知道
var v = a;
object o = new string("string");
Animal<int> a1 = new Animal<int>(); //在编译会找到这个类型把上面代码复制一份,并把泛型替换
Animal<float> b1 = new Animal<float>();
dynamic myvalue = 42; //只有当代码执行到这里才知道这里的类型,运行时确定
}
}
委托
委托
//封装:封装的函数对象,被调用的地址,甚至被调用的函数,调用者都可以封装成object
//解耦合
delegate,Action
多播
Func
//不同代码的耦合严重,各种数据乱飞,可读/维护/扩展难度大
//设计模式,技术来解决
* 封装
点外卖,打电话来点,每天都吃不一样,要记住每个店的电话
现在在软件上点,不需要知道电话是多少,做了封装把电话隐藏起来了
软件就作为了一个媒介
解耦
轮询/问有空 和 他什么时候有空主动回复你
这样可以两个并行的做事
除了delegate还有Action,也可以用匿名函数,在没有class时
Func是C#定义的模板类一个输入,一个输出,参数个数可以很多
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
/*
委托
//封装:封装的函数对象,被调用的地址,甚至被调用的函数,调用者都可以封装成object
//解耦合
关键字:
delegate,Action
多播
Func
*/
//不同代码的耦合严重,各种数据乱飞,可读/维护/扩展难度大
//设计模式,技术来解决
/*
* 封装
点外卖,打电话来点,每天都吃不一样,要记住每个店的电话
现在在软件上点,不需要知道电话是多少,做了封装把电话隐藏起来了
软件就作为了一个媒介
解耦
轮询/问有空 和 他什么时候有空主动回复你
这样可以两个并行的做事
*/
/*
除了delegate还有Action,也可以用匿名函数,在没有class时
Func是C#定义的模板类一个输入,一个输出,参数个数可以很多
*/
public class Me{
/*
public delegate void PhoneCall(int product,int cnt); //定义封装的函数长什么样子
//参数可以扩展,定义返回值和参数
public event PhoneCall phoneCallEvent; //创建了一个这样的实例
*/
public Action<int,int> phoneCallEvent; //返回值为空与上面两行一样,更方便一点
public void GoToEat(int product)
{
phoneCallEvent?.Invoke(product,1);
}
}
public class Shop
{
public void Cook(int product,int cnt) //需要上下形参一样
{ }
//下单以后也要通知我,给他一个委托,作完通过委托通知我
//委托作为参数,用函数类来封装,来实现类与类的解耦
public void Order(Func<int,int> order)
{
order(1);
}
}
public class Shop2
{
public void Cook(int product, int cnt) //需要上下形参一样
{
}
}
public class ExampleDelegate : MonoBehaviour
{
void Start()
{
Me me = new Me();
Shop shop = new Shop();
Shop2 shop2 = new Shop2();
me.phoneCallEvent += shop.Cook; //注册,把app信息注册到事件里
me.phoneCallEvent += shop2.Cook; //多播一下点两个外卖,再次传参数会一下调用两个
me.phoneCallEvent += (int a, int b) => { }; //两个函数,参数/内容
me.GoToEat(10); //我要吃第10号外卖,会调到下面一个事件 shop里的cook
shop.Order((int a) => { return a + 1; }); //这样也是委托的实现方法,委托作为参数
}
}
C# 反射
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Reflection; //加上反射的命名空间
//反射:https://blog.csdn.net/weixin_45136016/article/details/139095147
/*想在代码运行时查看某些信息,并切操作数据
可以看到程序的细节,想要知道黑盒内部就要拆开查看
关键字:
Filed
Attribute是一个属性 可以标记类/方法/变量,在之前标记后编译时会生成源数据
自定义Attribute可以扩展 HBO,继承表然后再加新的变量
*/
class LEIgfhne
{
[Bind("yeyuotc")] public int a;
}
class Bind : Attribute
{
string name;
public Bind(string name)
{
this.name = name;
}
//这里改了上面的特性也要加入传递信息,相当于打标签,需要额外的信息,机票的概念
}
public class ExampleReflection : MonoBehaviour
{
//默认私有的话在编译器里看不见
//public 就可以,但想让私有又在编译器里看就用 SerializeField
void Start()
{
LEIgfhne waffw = new LEIgfhne();
//从变量里知道:这个类里有多少成员变量
var fileds=waffw.GetType().GetFields(System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.NonPublic);
for(int i = 0; i < fileds.Length; i++)
{
FieldInfo field = fileds[i];
Bind b=Attribute.GetCustomAttribute(field, typeof(Bind)) as Bind;
if (b != null)
{
//B不为空就说明这个域可以拿出来这样一个Bind
Debug.Log("------yzh-----");
}
}
int aa = 0;
}
}
Linq
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Reflection;
using System.Linq;
//LINQ (Language Intergrated Query)
/*
数据查询语言,对数据进行查询的库, 数组/XML
此外还有第一个数/最后一个数/统计数量/求总和等等
像一个求平方和的操作
int numbers[]={1,2,3,4,5}
int squares[5];
for(int i=0;i<5;i++) squares[i]=numbers[i]*numbers[i];
更加优雅的方法
*/
public class ExampleReflection : MonoBehaviour
{
void Start()
{
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
int [] squares=numbers.Select(x => x * x).ToArray(); //这是一个lamba表达式求平方
//求完后再转ToArray,更高级的抽象/封装,可读性高很多
//想要判断有没有数字大于x,c++就要for循环但C#可以用any里面用lamda表达式,可以用函数封装起来
bool s=numbers.Any(x => { return x > 3; });
if (s)
{
//判断完再用where找再ToArray就行
int [] sss=numbers.Where(x => x > 3).ToArray();
}
}
}