分布类
分部类
- 把一个类分成几部分来声明
- 使用关键字partial
- 分部描述一个类
- 增加程序的扩展性
- 分部类可以写在多个脚本文件中
- 分部类中部可以有重复的成员
- 分部类的访问修饰符要一致
partial class Student{
public bool sex;
public string name;
}
partial class Student{
public bool sex;
public int id;
}partial class Student{
public bool sex;
public string name;
}
partial class Student{
public bool sex;
public int id;
}int a = 42;
Type type = a.GetType();//GetType是Object中的方法
Console.WriteLine(type);//System.Int32
//通过typeof 传入类名 也可以得到对象的type
Type type2 = typeof(int);
Console.WriteLine(type2);//System.Int32
//通过类的名字 也可以获取类型
//类名要包含命名空间 不然找不到
Type type3 = Type.GetType("System.Int32");
Console.WriteLine(type3);//System.Int32
//虽然有三个变量 但Type 1 2 3 指向的是一个房间//先得到Type
Type t = typeof(Test);
//得到所有的公共成员(包括构造函数) 需要引用System.Reflection;
MemberInfo[] infos = t.GetMembers();
foreach(var item in infos){
Console.WriteLine(item);
}//先得到Type
Type t = typeof(Test);
//得到所有的构造函数
ConstructorInfo[] ctors = t.GetConstructors();
foreach(var item in ctors){
Console.WriteLine(item);
}//先得到Type
Type t = typeof(Test);
//通过GetConstructor得到一个构造函数
//GetConstructor需要传入一个Type数组 数组中内容按顺序是参数类型
//得无参构造可以new一个长度为0的Type数组
ConstructorInfo info = t.GetConstructor(new Type[0]);
//执行无参构造
Test t = info.Invoke(null) as Test;//无参构造没有参数 传入null 返回object
//得有参构造
ConstructorInfo info2 = t.GetConstructor(new Type[]{typeof(int),typeof(string)});
//执行有参构造
Test t2 = info2.Invoke(new object[]{3,"阿拉拉"}) as Test;//先得到Type
Type t = typeof(string);
MethodInfo[] methods = t.GetMethods();
foreach(var item in methods){
Console.WriteLine(item);
}//先得到Type
Type t = typeof(string);
//第一个参数传方法名 第二个参数传type数组
MethodInfo method = t.GetMethods("Substring",new Type[]{typeof(int),typeof(int)});
//调用该方法
string str = "hellow";
//第一个参数 相当于是 哪个对象要执行这个成员方法
method.Invoke(str,new object[]{2,3});//llo
//如果是静态的 第一个参数传null
method.Invoke(null,new object[]{2,3});//llo//先得到Type
Type t = typeof(Test);
FieldInfo[] fieldInfos = t.GetFields();
foreach(var item in fieldInfos){
Console.WriteLine(item);
}//先得到Type
Type t = typeof(Test);
FildInfo info = t.GetFild("变量名");一般用来得别的程序集里的值
using System.Threading;
class Test{
public Main(){
//开启一个新的线程 需要传入一个委托类型
Thread t = new Thread(NewThreadLogic);
//启动线程 默认是前台线程
t.Start();
}
static void NewThreadLogic(){
//新开线程 执行的代码逻辑
while(true){
//前台线程:当主线程的代码执行完 依然不会停止 可能会导致进程无法正常关闭
Console.WriteLine("新的线程");
}
}
}后台线程
t.IsBackground = true;//设置为后台线程 方法一:将线程置空
参数默认值
static int Speak(string str = "我不想说话"){
}//泛型类
class TestClass<T,K>{
public T value;
public K value2;
}
TestClass<int,string> t = new TestClass<int,string>();
t.value = 10;
t.value2 = "阿拉拉";泛型接口
interface TestInterFace<T>{
T Value{get;set;}
}
class Test : TestInterFace<int>{
public int Value{
get{ return 10;}
set;
}
}泛型方法
vob关键字
class Fater{
public int age;
public string name;
public void Speak(){
Console.WriteLine("我是父类");
}
//虚函数
public virtual void Sing(){
Console.WriteLine("我是父类~~~~~~");
}
}
class Son:Fater{
public new void Speak(){
Console.WriteLine("我是子类");
}
//重写父类方法 多态
public override void Sing(){
//可通过base保留父类的行为
//base.Sing();
Console.WriteLine("我是子类~~~~~~");
}
}
Fater f = new Son();
f.Speak();//我是父类
f.Sing();//我是子类~~~~~~~absetract class Fruits{
//抽象类中可以包含成员属性
public string name;
//抽象方法没有方法体
public abstract void Bad();
}
absetract class Apple : Fruits{
//抽象类中可以包含成员属性
public string name;
//抽象方法必须被重写
public override void Bad(){
Console.WriteLine("阿拉拉");
}
}抽象类和接口的区别:
class Person{
private string name;
private int age;
public string Name{
get{
return name;
}
set{
//关键字value 用来表示外部传入的值
name = value;
}
}
}
//使用
Person p = new Person();
p.Name = "罗杰";get和set 可以添加访问修饰符
class Person{
private string name;
private int age;
public string Name{
//不可以在外面获得
private get{
return name;
}
set{
//关键字value 用来表示外部传入的值
name = value;
}
}
}
//使用
Person p = new Person();
p.Name = "罗杰";//报错自动属性
class CustomList : IEumerable,IEnumerator{
private int[] list;
private int index = -1;
public CustomList(){
list = {1,2,3,4,5,6,7,8,9};
}
//只要实现了IEumerable接口 Foreach就不会报错
public IEnumerator GetEnumerator(){
Reset();
return this;
}
//IEnumerator接口的方法
//代表当前的元素
public object Current => list[index];
public void Reset(){
index = -1;
}
public bool MoveNext(){
index++;
return lsit.Length>index;
}
}foreach(var item in CustomList){
Console.WriteLine(item);//1 2 3 4 5 6 7 8 9
}class CustomList : IEumerable{
private int[] list;
private int index = -1;
public CustomList(){
list = {1,2,3,4,5,6,7,8,9};
}
//只要实现了IEumerable接口 Foreach就不会报错
public IEnumerator GetEnumerator(){
for(int i =0;i<list.Length;i++){
//yield关键字 配合迭代器使用的
//可以理解为 暂时返回 保留当前状态
//C#语法糖
yield return list[i];
}
}
}void Fun(int a){
print(a);
++a;
Fun(a);
return;
}| 关键字 | 占用字节数 | 取值范围 |
|---|---|---|
| sbyte | 1 | -128~127 |
| byte | 1 | 0~255 |
| short | 2 | -32768~32767 |
| ushort | 2 | 0~65535 |
| int | 4 | -2147483648~2147483647 |
| uint | 4 | 0~4292967295 |
| long | 8 | -9223372036854775808~9223372036854775808 |
| ulong | 8 | 0~18446744073709551615 |
| char | 2 | 0~65535 |
| float | 4 | 存储7到8位有效数字 根据编译器不同 有效数字可能不一样 |
| double | 8 | 存储15~17位有效数字 |
| bool | (true,false) | |
| decimal | 16 | 存储27~28位有效数字 |
File->Build Setting 将场景添加到Scence in Build
ScenceManager.LoadScence("场景名");//可传入多个int类型的参数
static int Sum(params int[] arr){
}
Sum(1,2,3,4,5);using System;
using System.Collections;
using System.Reflection;
using UnityEngine;
public class PlayerPrefsDataMgr
{
private static PlayerPrefsDataMgr _instance = new PlayerPrefsDataMgr();
public static PlayerPrefsDataMgr Instance
{
get
{
return _instance;
}
private set
{
}
}
private PlayerPrefsDataMgr()
{
}
/// <summary>
/// 保存数据
/// </summary>
/// <param name="obj">要保存的对象</param>
/// <param name="key">唯一值</param>
public void SaveData(object obj, string key)
{
Type type = obj.GetType();
FieldInfo[] fields = type.GetFields();
string keyName;
for (int i = 0; i < fields.Length; i++)
{
keyName = key + "_" + type.Name + "_" + fields[i].FieldType.Name + "_" + fields[i].Name;
SaveValue(keyName, fields[i].GetValue(obj));
}
PlayerPrefs.Save();
}
/// <summary>
/// 获得数据
/// </summary>
/// <param name="type">传入对象类型</param>
/// <param name="key">唯一值Type</param>
/// <returns></returns>
public object GetData(Type type, string key)
{
object obj = Activator.CreateInstance(type);
FieldInfo[] fildinfo = type.GetFields();
string keyName;
foreach (var info in fildinfo)
{
keyName = key + "_" + type.Name + "_" + info.FieldType.Name + "_" + info.Name;
Debug.Log(keyName);
info.SetValue(obj, GetValue(info.FieldType, keyName));
}
return obj;
}
/// <summary>
/// 把数据存入PlayerPrefs
/// </summary>
/// <param name="keyName"></param>
/// <param name="value"></param>
private void SaveValue(string keyName, object value)
{
Type type = value.GetType();
if (type == typeof(string)) PlayerPrefs.SetString(keyName, value.ToString());
else if (type == typeof(int)) PlayerPrefs.SetInt(keyName, (int)value);
else if (type == typeof(float)) PlayerPrefs.SetFloat(keyName, (float)value);
else if (type == typeof(bool)) PlayerPrefs.SetInt(keyName, (bool)value ? 1 : 0);
else if (typeof(IList).IsAssignableFrom(type))
{
IList list = value as IList;
PlayerPrefs.SetInt(keyName, list.Count);
for (int i = 0; i < list.Count; i++)
{
SaveValue(keyName + "_" + i, list[i]);
}
}
else if (typeof(IDictionary).IsAssignableFrom(type))
{
IDictionary dict = value as IDictionary;
PlayerPrefs.SetInt(keyName, dict.Count);
var keys = dict.Keys;
int index = 0;
foreach (var key in dict.Keys)
{
SaveValue(keyName + "_" + index + "_" + "key", key);
SaveValue(keyName + "_" + index + "_" + "value", dict[key]);
index++;
}
}
else
{
SaveData(value, keyName);
}
}
/// <summary>
/// 把数据从PlayerPrefs取出
/// </summary>
/// <param name="type"></param>
/// <param name="key"></param>
/// <returns></returns>
private object GetValue(Type type, string key)
{
if (type == typeof(string)) return PlayerPrefs.GetString(key);
else if (type == typeof(int)) return PlayerPrefs.GetInt(key);
else if (type == typeof(float)) return PlayerPrefs.GetFloat(key);
else if (type == typeof(bool)) return PlayerPrefs.GetInt(key) == 1;
else if (typeof(IList).IsAssignableFrom(type))
{
IList list = Activator.CreateInstance(type) as IList;
for (int i = 0; i < PlayerPrefs.GetInt(key); i++)
{
list.Add(GetValue(type.GetGenericArguments()[0], key + "_" + i));
}
return list;
}
else if (typeof(IDictionary).IsAssignableFrom(type))
{
IDictionary dict = Activator.CreateInstance(type) as IDictionary;
Type keyType = type.GetGenericArguments()[0];
Type valueType = type.GetGenericArguments()[1];
for (int i = 0; i < PlayerPrefs.GetInt(key); i++)
{
dict.Add(GetValue(keyType, key + "_" + i + "_" + "key"), GetValue(valueType, key + "_" + i + "_" + "value"));
}
return dict;
}
else
{
return GetData(type, key);
}
}
}openssl passwd 12345echo "admin:fIHcRVEKijgoM" > htpasswdauth_basic "Please input password";
auth_basic_user_file /usr/share/nginx/passwd/htpasswd;安装php
sudo apt install php7.4-fpm
sudo apt install php7.4-{sqlite3,curl,sockets,mbstring,iconv}调整php-fpm的进程数量
pm = static
pm.max_children = 2
pm.max_requests = 500nginx开启php支持
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}开启伪链
nano /etc/ssh/sshd_config#修改默认端口
Prot 25428adduser username
apt update && apt install sudo
visudo#在 User Privilege Specification 下加入一行 username ALL=(ALL) NOPASSWD: ALL
username ALL=(ALL) NOPASSWD: ALLnano /etc/ssh/sshd_config
#PermitRootLogin Yes改为no
PermitRootLogin no
systemctl restart ssh运行PuTTYgen
适用于泛型接口和泛型委托
协变:out修饰符修饰泛型参数 只能作为返回值类型
逆变:in修饰符修饰泛型参数 只能作为参数使用
协变和逆变在泛型委托函数中中:
协变:泛型委托参数为父类 装子类泛型委托
逆变:泛型委托参数为子类 装父类泛型委托
当子类继承父类,子类重写父类的方法时,如果使用父类装子类对象 调用重写的方法时 会执行父类中的方法。
可将父类的函数声明为虚函数,子类使用override关键字重写父类方法,调用重写的方法时 会执行子类中的方法。
using System;
namespace csharpleran
{
struct StructTest
{
public class Fater {
public Fater(int i) {
Console.WriteLine(i);
}
public virtual void Eat(string str) {
Console.WriteLine("Fater virtual Eat");
}
public void Eat() {
Console.WriteLine("Fater Eat");
}
}
public class Player : Fater {
/// <summary>
/// 子类调用父类的构造函数
/// </summary>
/// <param name="i"></param>
public Player(int i):base(i)
{
Console.WriteLine("子类子类子类");
}
/// <summary>
/// 调用重载构造函数
/// </summary>
public Player() : this(1) {
}
public override void Eat(string str)
{
Console.WriteLine("Player override Eat");
}
public new void Eat()
{
Console.WriteLine("Player Eat");
}
}
class Program
{
static void Main(string[] args)
{
Fater f = new Player();
f.Eat(); //Fater Eat
(f as Player).Eat();//Player Eat
f.Eat("");//Player override Eat
(f as Fater).Eat("");//Player virtual Eat
}
}
}
}is 返回一个bool 判断一个对象是否是指定类的对象 as可以将一个对象转换为指定类型的对象(用于父类容器 装子类对象 可通过as调用子类对象中的方法)