Bootstrap

Unity C#底层原理(二)

委托
  1. 方法的容器:委托可以存储一个或多个方法的引用。可以使用委托对象来调用这些方法。
  2. 函数/方法的变量类型:委托类型可以像变量一样声明和使用,存储方法的引用。
  3. 存储、传递方法:委托可以作为参数传递给方法,也可以作为方法的返回值。这使得方法可以接收其他方法作为参数,或返回方法。
  4. 本质是一个类:每个委托类型在编译时都会生成一个类,继承自 System.Delegate 或
    System.MulticastDelegate。这个类提供了 Invoke 方法,用于调用委托所指向的方法。
事件

与委托使用方法一样
不同点:事件不可以在外部被调用,不可以在外部置空
只可以在外部进行+=、-=的操作

 public class Card  
    {
        public Card()
        {
            Test.MAC?.Invoke();

            Test.MAC_args?.Invoke("ABS");
        }
    }

    sealed class Test
    {
        public static MyAction MAC;
        public static MyActionWithArgs<int,string> MAC_args;
        public Test()
        {
            MAC += () => { };//lambda表达式
            MAC += delegate {  };//匿名函数

            MAC_args += (str) =>
            {
                Debug.LogError(str);
                return 1;
            };
            MAC_args += delegate(string str) { Debug.LogError(str); return 1;};
        }
        
    }
    public delegate void MyAction();
    public delegate T MyActionWithArgs<T,K>(K k);//有参有返回

协变

1、out 修饰的泛型类型 只能作为返回值,不能作为参数(如Func)
2、父类泛型委托容器可以装子类泛型委托容器(如下方法)

 public class CovarianceClass
    {
        delegate T Covariance<out T>();
        public CovarianceClass()
        {
            Covariance<Son> son = () => { return new Son();};
            Covariance<Father> father = son;//父类容器装子类容器,协变
        }
    }

    public class Father
    {
    }

    public class Son : Father
    {
    }

逆变

1、in 修饰的泛型类型,表示只能作为参数,不能返回(如Action)
2、子类泛型容器可以装父类泛型容器(如下方法)

 public class ContravarianceClass
    {
       delegate void Contravariance<in T>(T t);

       public ContravarianceClass()
       {
           Contravariance<Father> father = (t) => { };
           Contravariance<Son> son = father;//子类容器可以装父类容器,逆变
       }
    }

    public class Father
    {
    }

    public class Son : Father
    {
    }

typeof

用于获取Type

   public enum SpAtlasEnum
    {
        Cards_00,
    }
  
            SpAtlasEnum A = (SpAtlasEnum)Enum.Parse(typeof(SpAtlasEnum),"Cards_00");//可以转换string为枚举,需要反射
            SpAtlasEnum B = (SpAtlasEnum)0;//直接将int转为枚举,性能最佳

Type

dll一般需要运行过才会生成

        public GameManager()
        {
            Assembly assembly = Assembly.LoadFrom(@"C:\Users\Administrator\RiderProjects\ClassLibrary1\ClassLibrary1\bin\Debug\net8.0\ClassLibrary1.dll");//找到这个dll
            Type[] assemblyAllInfo = assembly.GetTypes();
            for (int i = 0; i < assemblyAllInfo.Length; i++)
            {
                Debug.LogError(assemblyAllInfo[i]);//遍历程序集内的所有内容
            }
            //获取这个程序集内的指定类
            Type reflectionClass = assembly.GetType("Reflection_Namespace.Reflection_Class");
            //将他实例化
            object obj = Activator.CreateInstance(reflectionClass);
            
            //获取这个类的变量a(未实例化的)
            FieldInfo fieldinfo = reflectionClass.GetField("a");
            
            //设置该变量a指定 实例化的obj  
            fieldinfo.SetValue(obj,131);
            //打印实例化的obj的变量a的值
            Debug.LogError(fieldinfo.GetValue(obj));
            
            //同理 获取方法(未实例化的)
            MethodInfo methodInfo = reflectionClass.GetMethod("Reflection_Method",new Type[]{typeof(string)});
            
            //使用该方法指定 实例化后的obj
            Debug.LogError(methodInfo.Invoke(obj, new object[] {"Reflection" })); 
            
        }
        }

;