1.Lambda表达式
可以将lambad表达式理解为匿名函数的简写
它除了写法不同外,使用上和匿名函数一模一样
都是和委托或者事件配合使用的
//匿名函数
//delegate(参数列表)
//{
//}
//lambda表达式
//(参数列表) =>
//{
//函数体
//}
//1.无参无返回值
Action a = () =>
{
Debug.Log("Lambda");
};
a();
//2.有参
Action<int> a2 = (int value) =>
{
Debug.Log("参数lambda");
};
a2(10);
//3.参数类型可以省略,参数类型和委托或者事件一致
Action<int> a3 = (value) =>
{
Debug.Log("无类型参数");
};
a3(100);
//4.有返回值
Func<string, int> a4 = (value) =>
{
Debug.Log("返回值");
return 1;
};
a4("a");
闭包:
内层的函数可以引用包含在它外层的函数的变量
即使外层函数的执行已经终止
注意:
该变量提供的值并非变量创建时的值,而是在父函数范围内的最终值。
public class test : MonoBehaviour
{
private void Start()
{
Tes tes = new Tes();
tes.DoThing();
}
}
class Tes
{
public event Action action;
/// <summary>
/// 这里就形成了闭包
/// 当构造函数执行完毕,声明的临时变量value生命周期被改变了
/// </summary>
public Tes()
{
int value = 10;
action = () =>
{
Debug.Log(value);
};
for (int i = 0; i < 5; i++)
{
//想要实现for循环存进事件不同的i值,需要在循环内部声明一个临时变量
//每次存储的index不是同一个index
int index = i;
//假如事件注册进5个i变量,但是当使用时,变量的值都是for循环的最终值5,
action += () =>
{
Debug.Log(index);
};
}
}
public void DoThing()
{
action();
}
}
2.List排序
A.自带排序:
//list自带排序
List<int> list = new List<int>();
list.Add(6);
list.Add(1);
list.Add(5);
list.Add(3);
list.Add(6);
list.Add(5);
list.Sort();
B.自定义排序:
public class test : MonoBehaviour
{
private void Start()
{
List<Items> ite = new List<Items>();
ite.Add(new Items(2));
ite.Add(new Items(21));
ite.Add(new Items(12));
ite.Add(new Items(52));
ite.Add(new Items(32));
ite.Sort();
for (int i = 0; i < ite.Count; i++)
{
Debug.Log(ite[i].id);
}
}
}
/// <summary>
/// 继承IComparable接口实现对比
/// </summary>
class Items : IComparable<Items>
{
public int id;
public Items(int id) {
this.id = id;
}
public int CompareTo(Items other)
{
//返回值的含义
//小于0:
//放在传入对象的前面
//等于0:
//保持当前的位置不变
//大于0:
//放在传入对象的后面
//可以简单理解传入对象的位置就是
//如果你的返回为负数就放在它的左边也就前面
//如果你返回正数就放在它的右边也就是后面
if (this.id < other.id)
{
return -1;
}
else
{
return 1;
}
}
}
C.通过委托函数实现排序
public class test : MonoBehaviour
{
private void Start()
{
List<ShopItem> items = new List<ShopItem>();
items.Add(new ShopItem(2));
items.Add(new ShopItem(13));
items.Add(new ShopItem(24));
items.Add(new ShopItem(15));
//1.调用函数
items.Sort(SortShop);
//2.匿名函数
//items.Sort(delegate (ShopItem a, ShopItem b)
//{
// if (a.id > b.id)
// {
// return 1;
// }
// else
// {
// return -1;
// }
//});
//3.lambda表达式
//items.Sort((a, b) =>
//{
// return a.id > b.id ? 1 : -1;
//});
for(int i = 0; i < items.Count; i++)
{
Debug.Log(items[i].id);
}
}
static int SortShop(ShopItem a,ShopItem b)
{
//传入的两个对象,为列表中两个对象,进行两两比较
//用左边的和右边的比较,负数在左边,正数在右边
if (a.id > b.id)
{
return 1;
}
else
{
return -1;
}
}
}
class ShopItem
{
public int id;
public ShopItem(int id)
{
this.id = id;
}
}
public class test : MonoBehaviour
{
private void Start()
{
List<ShopItem> items = new List<ShopItem>();
items.Add(new ShopItem(1,2,3,4));
items.Add(new ShopItem(4,3,2,1));
items.Add(new ShopItem(6,7,8,9));
items.Add(new ShopItem(9,8,7,6));
items.Add(new ShopItem(3,4,5,6));
int item = UnityEngine.Random.Range(0, 4);
items.Sort((a, b) =>
{
int index = 0;
switch (item)
{
case 0:
index = a.gong > b.gong ? 1 : -1;
break;
case 1:
index = a.fang > b.fang ? 1 : -1;
break;
case 2:
index = a.xue > b.xue ? 1 : -1;
break;
case 3:
index = a.fan > b.fan ? 1 : -1;
break;
}
return index;
});
for (int i = 0; i < items.Count; i++)
{
switch (item)
{
case 0:
Debug.Log(items[i].gong);
break;
case 1:
Debug.Log(items[i].fang);
break;
case 2:
Debug.Log(items[i].xue);
break;
case 3:
Debug.Log(items[i].fan);
break;
}
}
}
}
class ShopItem
{
public int gong;
public int fang;
public int xue;
public int fan;
public ShopItem(int gong,int fang,int xue,int fan)
{
this.gong = gong;
this.fang = fang;
this.xue = xue;
this.fan = fan;
}
}
3.协变和逆变
协变:
和谐的变化,自然的变化
因为里氏替换原则 父类可以装子类
比如string变成object
感受是和谐的
逆变:
逆常规的变化,不正常的变化
因为里氏替换原则 父类可以装子类 但是子类不能装父类
所以比如object变成string
感受是不和谐的
协变和逆变是用来修饰泛型的
协变:out
逆变:in
用于在泛型中 修饰 泛型字母的
只有泛型接口和泛型委托能使用
//1.返回值和参数
//用out修饰的泛型只能作为返回值
delegate T Test out<out T>();
//用in修饰的泛型只能作为参数
delegate void Test In<in T>(T t);
public class test : MonoBehaviour
{
//用out修饰的泛型只能作为返回值
delegate T TestOut<out T>();
//用in修饰的泛型只能作为参数
delegate void TestIn<in T>(T t);
private void Start()
{
//协变 父类总是能被子类替换
TestOut<Son> os = () =>
{
return new Son();
};
TestOut<Father> of = os;
//实际返回的是os里面装的函数 返回的是son
Father f = of();
//逆变
TestIn<Father> iF = (value) =>
{
};
TestIn<Son> iS = iF;
//实际上 调用的是iF
iS(new Son());
}
}
class Father{}
class Son : Father{}