一、扩展方法
定义:
using System;
namespace WindowsFormsApp3
{
public static class A
{
public static void Boy(this int x)
{
Console.WriteLine(x);
}
}
}
调用:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp3
{
internal static class Program
{
static void Main()
{
3.Boy();
A.Boy(9);
while (true) ;
}
}
}
二、匿名类型
简单的使用:
//创建使用匿名类型对象
var person = new { Name = "L", Age = 17 };
Console.WriteLine($"{ person.Name},{person.Age}");
//动态类型处理匿名类型对象
//缺点:属性名写错了,也不会报错,运行时出错
dynamic GetPerson()
{
return new { Name = "TY", Age = 46 };
}
dynamic x = GetPerson();
Console.WriteLine($"{ x.Name},{x.Age}");
//解决
//指定类型接受匿名类型对象
//这个技巧只有在同一个程序集中的代码才有效
var cup = new { Name = "", Age = 0 };
cup = GetPerson();
Console.WriteLine($"{ cup.Name},{cup.Age}");
通过反射获取匿名类型数据项(测试匿名类型作参数)
using System;
using System.Reflection;
using System.Threading;
namespace ConsoleApp1
{
internal class Program
{
public class Test
{
public static void One(object obj)
{
Type t =obj.GetType();
PropertyInfo pName = t.GetProperty("Name");
PropertyInfo pAge = t.GetProperty("Age");
Console.WriteLine($"匿名类型:{t.Name}");
Console.WriteLine($"Name:{pName?.GetValue(obj)},Age:{pAge?.GetValue(obj)}");
}
}
static void Main(string[] args)
{
Test.One(new { Name = "abc", Age = "123" });
while(true) {
Thread.Sleep(1000);
}
return;
}
}
}
linq支持对匿名对象集合的查询处理
using System;
using System.Linq;
using System.Threading;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
//linq支持对匿名对象集合的查询处理
var people = new[]
{
new{Name = "a",Age=30},
new{Name = "dh",Age=32},
new{Name = "fl",Age=35},
};
var query = from p in people
where p.Age > 30
select p;
foreach(var person in query)
{
Console.WriteLine($"Name:{person.Name},Age:{person.Age}");
}
while(true) {
Thread.Sleep(1000);
}
return;
}
}
}
//使用 LINQ 进行联合查询,查询学生信息以及对应的班级信息
using System;
using System.Linq;
using System.Threading;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
var studentList = new[]
{
new{Name="a",Age=33 ,Gender = "男",ClassId=1},
new{Name="b",Age=33 ,Gender = "男",ClassId=1},
new{Name="c",Age=33 ,Gender = "男",ClassId=1},
new{Name="d",Age=33 ,Gender = "男",ClassId=1},
new{Name="e",Age=33 ,Gender = "男",ClassId=1},
new{Name="f",Age=33 ,Gender = "男",ClassId=3},
new{Name="g",Age=33 ,Gender = "男",ClassId=3},
new{Name="h",Age=33 ,Gender = "男",ClassId=3},
new{Name="i",Age=33 ,Gender = "男",ClassId=3},
new{Name="j",Age=33 ,Gender = "男",ClassId=2},
new{Name="k",Age=33 ,Gender = "男",ClassId=2},
new{Name="l",Age=33 ,Gender = "男",ClassId=2},
};
var classList = new[]
{
new{ClassName="A",Teacher="Aer",Id=1},
new{ClassName="B",Teacher="Ber",Id=2},
new{ClassName="C",Teacher="Cer",Id=3},
};
//使用 LINQ 进行联合查询,查询学生信息以及对应的班级信息
var result = from s in studentList
join c in classList on s.ClassId equals c.Id
select new
{
学生姓名 = s.Name,
年龄 = s.Age,
性别 = s.Gender,
班级名称 = c.ClassName,
班级教师 = c.Teacher
};
//输出查询结果
foreach(var item in result)
{
Console.WriteLine($"学生姓名:{item.学生姓名},年龄:{item.年龄},性别:{item.性别},班级名称:{item.班级名称},班级教师:{item.班级教师}");
}
while(true) {
Thread.Sleep(1000);
}
return;
}
}
}
简写:自动以属性为名称
using System;
using System.Linq;
using System.Threading;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
var studentList = new[]
{
new{Name="a",Age=33 ,Gender = "男",Id=1},
new{Name="f",Age=33 ,Gender = "男",Id=3},
new{Name="j",Age=33 ,Gender = "男",Id=2},
};
//使用 LINQ 进行联合查询,查询学生信息以及对应的班级信息
//这里没写属性名,自动以属性为名称
var result = from s in studentList
select new
{
s.Id,
s.Name,
};
//输出查询结果
foreach(var item in result)
{
Console.WriteLine($"学生ID:{item.Id},学生姓名:{item.Name}");
}
while(true) {
Thread.Sleep(1000);
}
return;
}
}
}
三、元组
使用元组交互元素
string str1 = "aaa";
string str2 = "BBB";
Console.WriteLine(str1+" : "+str2);
(str1, str2) = (str2, str1);
Console.WriteLine(str1 + " : " + str2);
定义与使用:
使用元组(),将多个数据元素构成一个轻型数据结构
(string,int) x = new ValueTuple<string,int>(“Bob”,25);
(string,int) x = ValueTuple.Create(“Bob”,25);
using System;
namespace ConsoleApp2
{
internal class Program
{
static void Main(string[] args)
{
//使用元组(),将多个数据元素构成一个轻型数据结构
//(string, int) x = new ValueTuple<string, int>("Bob", 25);
//(string, int) x = ValueTuple.Create("Bob", 25);
(string, int) x = ("aaa", 99);
var y = ("bbb", 19);
Console.WriteLine($"姓名:{x.Item1},年龄:{x.Item2}");
}
}
}
使用字段名
using System;
namespace ConsoleApp2
{
internal class Program
{
static void Main(string[] args)
{
//使用命名字段
var x = (name: "asd", age: 99);
Console.WriteLine($"姓名:{x.name},\t年龄:{x.age}");
(string name, int age) y = ("KL", 12);
Console.WriteLine($"姓名:{y.name},\t年龄:{y.age}");
while (true) ;
}
}
}
元组的解构 与 弃元
using System;
namespace ConsoleApp2
{
internal class Program
{
static void Main(string[] args)
{
//元组的解构
var (name, age) = ("qaz", 10);
Console.WriteLine($"姓名:{name},年龄:{age}");
//弃元 就是放弃不需要的元素
var tuple = (1, "a", 3.12);
var(_,letter,_)=tuple;
Console.WriteLine(letter);
while (true) ;
}
}
}
元组作为入参和返回值的用法
using System;
namespace ConsoleApp2
{
internal class Program
{
//元组作为参数
void ProcessTuple((string Name,int Age) person)
{
Console.WriteLine($"Name:{person.Name},Age:{person.Age}");
}
//元组作为返回类型
(int Sum,int Product)GetSumAndProduct(int a,int b)
{
return (a + b, a * b);
}
static void Main(string[] args)
{
Program program = new Program();
//元组作为参数
program.ProcessTuple(("A", 25));
//元组作为返回类型
var result = program.GetSumAndProduct(2, 3);
Console.WriteLine($"和:{result.Sum},积{result.Product}");
while (true) ;
}
}
}
元组类型支持相等运算符 == != ,比较的是各个元素
using System;
namespace ConsoleApp2
{
internal class Program
{
static void Main(string[] args)
{
//元组类型支持相等运算符 == != ,比较的是各个元素
var data = (2, 2.3);
if ((2, 2.2) == data)
{
Console.WriteLine("相等");
}
else
{
Console.WriteLine("不相等");
}
while (true) ;
}
}
}
LINQ查询
using System;
using System.Linq;
namespace ConsoleApp2
{
internal class Program
{
static void Main(string[] args)
{
var studentList = new[] {
(Name: "af",Age: 99,Gender: "男",ClassId:1),
(Name: "af",Age: 99,Gender: "男",ClassId:2),
(Name: "af",Age: 99,Gender: "男",ClassId:2),
(Name: "af",Age: 99,Gender: "男",ClassId:2),
(Name: "af",Age: 99,Gender: "男",ClassId:3)
};
var classList = new[] {
(ClassName: "YU1",Teacher: "LL1",Id:1),
(ClassName: "YU2",Teacher: "LL2",Id:2),
(ClassName: "YU3",Teacher: "LL3",Id:3)
};
//使用 LINQ 进行联合查询 学生信息以及对应的班级信息
var result = from s in studentList
join c in classList on s.ClassId equals c.Id
select (
学生姓名: s.Name,
年龄: s.Age,
性别: s.Gender,
班级名: c.ClassName,
班级教师: c.Teacher
);
//输出查询结果
foreach(var item in result )
{
Console.WriteLine($"学生姓名:{item.学生姓名},年龄{item.年龄}:,性别:{item.性别},班级名称:{item.班级名},班级教师:{item.班级教师}");
}
while (true) ;
}
}
}
元组可以修改,匿名对象不可以
using System;
using System.Linq;
namespace ConsoleApp2
{
internal class Program
{
static void Main(string[] args)
{
//元组可以修改,匿名对象不可以
var p = (name: "ABD", age: 69);
p.name = "LO";
Console.WriteLine(p);
while (true) ;
}
}
}
四、GDI
五、特性与反射
特性的说明:
等价于 java 中的 注解;作用就是在 类、方法、属性上加个钩子,作为标记或调用的入口
特性,通常是放到类、属性、方法上面,对其进行一个说明;信息的扩展
特性的使用:
必须继承 Atrribute,然后可以添加属性、方法等
使用中括号 加载其他类或方法的上面
反射:
c中 内存可访问单位可以是 指针的步长
更高级的一些语言 没有指针 又想更自由的访问 比类更小的地方(如:类里的 方法、属性)
,可以把他们叫元对象,拿到这些元对象的技术,就叫做反射
反射可以做到的事情:
动态创建对象:根据字符串名称创建类型的新实例。
获取类型信息:查询类型的名字、命名空间、基类、接口等。
调用方法:调用类型的方法,即使这些方法是私有的。
访问字段和属性:读取和设置字段或属性的值。
例子 1(用反射抓取有指定特性的类或方法):
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
namespace MVCFormApp
{
public partial class Form1 : Form
{
List<Type> heroTypes;
public Form1()
{
InitializeComponent();
}
private void 人物_Click(object sender, EventArgs e)
{
//加载所有人物
heroTypes = Assembly.GetExecutingAssembly().GetTypes()
.Where(t=>t.GetCustomAttributes(typeof(HeroAttribute),false).Any())
.ToList();
//打印
foreach(Type t in heroTypes)
{
Console.WriteLine(t.Name);
}
}
private void 行为_Click(object sender, EventArgs e)
{
for (int i = 0;i < heroTypes.Count; ++i){
//创建对象
var selectedHeroType = heroTypes[i];
object hero = Activator.CreateInstance(selectedHeroType);
//获取方法
var skillMethods = selectedHeroType.GetMethods()
.Where(m => m.GetCustomAttributes(typeof(SkillAttribute), false).Any())
.ToList();
//执行方法
foreach(MethodInfo mi in skillMethods)
{
mi.Invoke(hero, null);
}
}
}
}
//定义标签
public class HeroAttribute : Attribute { }
public class SkillAttribute : Attribute { }
[HeroAttribute]
class Person1
{
[SkillAttribute]
public void A()
{
Console.WriteLine("HHHHHHH1");
}
[SkillAttribute]
public void AA()
{
Console.WriteLine("HHHHHHH2");
}
[SkillAttribute]
public void AAA()
{
Console.WriteLine("HHHHHHH3");
}
}
[HeroAttribute]
class Person2
{
[SkillAttribute]
private void B()
{
Console.WriteLine("JJJJJJJ");
}
}
[HeroAttribute]
class Person3
{
[SkillAttribute]
private void C()
{
Console.WriteLine("KKKKKKKKK");
}
}
}
例子 2 (用反射拿到绑定 特性 的类 、类里的属性、类里的方法)
using System;
using System.Linq;
namespace ConsoleApp1
{
//定义---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//一个自定义的类
//特性的使用说明 可以写在类上 可以写在方法上 可以写在属性上 使用可以放多个特性 是否继承到子类
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public class MyCustomAttribute : Attribute
{
public MyCustomAttribute(int x)
{
propert1 = x;
}
public int propert1 { get; set; }
public int Method1()
{
Console.WriteLine($"this is Method1,propert1:{propert1}");
return 200;
}
}
//可以继承
public class MyCustomAttribute2 : MyCustomAttribute
{
public MyCustomAttribute2(int x = 0) : base(x)
{
}
}
//使用---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[MyCustomAttribute(1)]
[MyCustomAttribute(2)]
[MyCustomAttribute2]
public class A:Object
{
//增加标记
[MyCustomAttribute2]
public int propert1 { get; set; }
[MyCustomAttribute2]
public int propert2 { get; set; }
[MyCustomAttribute2]
public int propert3 { get; set; }
[MyCustomAttribute2]
public int propert4 { get; set; }
[MyCustomAttribute2]
public int propert5 { get; set; }
//注入信息
[MyCustomAttribute(10)]
public int Method1()
{
Console.WriteLine("this is Method1");
return 1;
}
[MyCustomAttribute(20)]
public int Method2()
{
Console.WriteLine("this is Method2");
return 2;
}
[MyCustomAttribute(30)]
public int Method3()
{
Console.WriteLine("this is Method3");
return 3;
}
}
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine();
Console.WriteLine("抓取类上的特性----------------------------------------------");
Test001();
Console.WriteLine();
Console.WriteLine("抓取属性上的特性----------------------------------------------");
Test002();
Console.WriteLine();
Console.WriteLine("抓取方法上的特性----------------------------------------------");
Test003();
//暂停
Console.ReadLine();
}
//获取类上的自定义特性
public static void Test001()
{
//获取类的类型
Type type = typeof(A);
//检查指定的类上有无 这个自定义的特性
if (type.IsDefined(typeof(MyCustomAttribute), true))
{
//把特性取出来
var myCusteomAttrivutes = type.GetCustomAttributes(typeof(MyCustomAttribute), true);
//遍历所有特性
foreach (var item in myCusteomAttrivutes)
{
//对拿到的特性 类,进行操作,就想平常的类一样
var m = (MyCustomAttribute)item;
m.Method1();
m.propert1 = 300;
m.Method1();
}
}
}
//获取类中的属性上的特性
public static void Test002()
{
//获取类的类型
Type classType = typeof(A);
//拿到这个类的所有属性
var properties = classType.GetProperties();
//遍历所有取出来的属性
foreach(var property in properties)
{
//检查这个属性上有没有指定的特性
if(property.IsDefined(typeof(MyCustomAttribute), true)){
//把属性上的特性取出来
var mCAs = property.GetCustomAttributes(typeof(MyCustomAttribute), true);
Console.WriteLine(property.Name + "-----");//打印下变量 的名字
foreach (var mCA in mCAs)
{
//对出来的 特性类进行操作
((MyCustomAttribute)mCA).Method1();
}
}
}
}
//获取类里的方法上的特性
public static void Test003()
{
//获取类的类型
Type classType = typeof(A);
//拿到这个类的所有方法
var methods = classType.GetMethods();
//遍历所有取出来的方法
foreach (var method in methods)
{
//检查这个方法上有没有指定的特性
if (method.IsDefined(typeof(MyCustomAttribute), true))
{
//把方法上的特性取出来
var mCAs = method.GetCustomAttributes(typeof(MyCustomAttribute), true);
Console.WriteLine(method.Name + "-----");//打印下方法 的名字
foreach (var mCA in mCAs)
{
//对出来的 特性类进行操作
((MyCustomAttribute)mCA).Method1();
}
}
}
}
}
}
用反射拿到类里的私有/静态 属性、方法
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
namespace MVCFormApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TestFunc();
}
private void TestFunc()
{
MyClass obj = new MyClass();
Type type = typeof(MyClass);
BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
FieldInfo fieldInfo = type.GetField("myField",flags);
fieldInfo?.SetValue(obj, "123");
Console.WriteLine(fieldInfo?.GetValue(obj));
PropertyInfo propertyInfo = type.GetProperty("myProperty", flags);
Console.WriteLine(propertyInfo?.GetValue(obj));
propertyInfo?.SetValue(obj, "重置的私有属性");
Console.WriteLine(propertyInfo?.GetValue(obj));
MethodInfo method = type.GetMethod("FunA", flags);
method?.Invoke(obj, null);
flags = BindingFlags.Static | BindingFlags.NonPublic;
fieldInfo = type.GetField("sField", flags);
Console.WriteLine(fieldInfo?.GetValue(null));
method = type.GetMethod("FunB", flags);
method?.Invoke(obj, null);
method?.Invoke(null,null);
}
}
class MyClass
{
private string myField = "私有字段";
private static string sField = "静态私有字段";
private string myProperty { get; set; } = "私有属性";
private void FunA()
{
Console.WriteLine("私有方法执行.");
}
private static void FunB()
{
Console.WriteLine("静态私有方法执行.");
}
}
}
用反射、接口、xml里的 字符串 跨库调用里的接口,实现解耦
reflection
ClassSon.cs------------------------------------------------------
namespace Reflection
{
internal class ClassSon : Interface1
{
//void say()
//{
// Console.WriteLine("I am Son1");
//}
public void say()
{
Console.WriteLine("I am son1");
}
}
}
-------------------------------------------------------------------
Interface1.cs------------------------------------------------------
namespace Reflection
{
internal interface Interface1
{
void say();
}
}
----------------------------------------------------------------
Program.cs------------------------------------------------------
using System.Reflection;
using System.Configuration;
using ClassLibrary2;
Console.WriteLine("Hello, World!");
//Test001();
Test002();
Console.ReadLine();
//调用同一程序集的接口 (Load)
static void Test001()
{
Reflection.Interface1 interface1 = (Reflection.Interface1)Assembly.Load("Reflection").CreateInstance("Reflection.ClassSon");
interface1.say();
}
//调用其他程序集接口 (LoadFrom)
static void Test002()
{
string assName = ConfigurationManager.AppSettings["assName"];
string className = ConfigurationManager.AppSettings["className"];
ClassLibrary2.Interface1 interface1 = (ClassLibrary2.Interface1)Assembly.LoadFrom(assName).CreateInstance(className);
interface1.say();
}
------------------------------------------------------
classLibrary1
Class1.cs-------------------------------------------------------------------
namespace ClassLibrary1
{
public class Class1 : Interface1
{
public void say()
{
Console.WriteLine("I am Class1");
}
}
}
--------------------------------------------------------------------------------
Interface1.cs-------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassLibrary1
{
public interface Interface1
{
void say();
}
}
--------------------------------------------------------------------------------
classLibrary2
Class1.cs-------------------------------------------------------------------
namespace ClassLibrary2
{
public class Class1 : Interface1
{
public void say()
{
Console.WriteLine("I am Class2");
}
}
}
--------------------------------------------------------------------------------
Interface.cs-------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassLibrary2
{
public interface Interface1
{
void say();
}
}
--------------------------------------------------------------------------------
官方提供的特性 的使用:Obsolete 、Serializable
对 弃用说明类(Obsolete)的 使用
using System;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
ClassA classA = new ClassA();
classA.a = 1;
classA.b = 1;
classA.method_a();
classA.method_b();
}
[Obsolete("该类已经过时,请使用 ClassB 类")]
class ClassA
{
[Obsolete("该属性已经过时,请使用属性 b")]
public int a { get; set; }
public int b { get; set; }
[Obsolete("该方法已经过时,请使用 method_b 方法")]
public void method_a()
{
Console.WriteLine("method_a");
}
public void method_b()
{
Console.WriteLine("method_b");
}
}
class ClassB{}
}
}
对 序列化特性(Serializable)的 使用
using System;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
}
[Serializable]
class ClassA
{
public int a { get; set; }
public int b { get; set; }
public ClassB classB;
public void method_a()
{
Console.WriteLine("method_a");
}
public void method_b()
{
Console.WriteLine("method_b");
}
}
[Serializable]
class ClassB{
public string c { get; set; }
}
}
}
六、泛型
使用举例(泛型类、泛型参数、泛型返回值)
using System;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
MyStack<int> stack = new MyStack<int>(10);
stack.Push(1);
stack.Push(2);
stack.Push(3);
stack.Push(4);
stack.Push(5);
stack.Push(6);
stack.Push(7);
stack.Push(8);
stack.Push(9);
stack.Push(0);
Console.WriteLine(stack.Pop());
Console.WriteLine(stack.Pop());
Console.WriteLine(stack.Pop());
Console.WriteLine(stack.Pop());
Console.WriteLine(stack.Pop());
Console.WriteLine(stack.Pop());
Console.WriteLine(stack.Pop());
Console.WriteLine(stack.Pop());
Console.WriteLine(stack.Pop());
Console.WriteLine(stack.Pop());
}
}
//出入栈泛型
public class MyStack<T>
{
//泛型数组
private T[] stack;
//元素位置
private int stackIndex;
//数据容量
private int size;
public MyStack(int size)
{
this.size = size;
this.stack = new T[size];
this.stackIndex = -1;//入栈开始是0,每次先加1
}
//元素入栈
public void Push(T item)
{
if(this.stackIndex >= this.size)
Console.WriteLine("栈空间已满");
else
{
this.stackIndex++;
this.stack[stackIndex] = item;
}
}
//元素出栈
public T Pop()
{
T data = this.stack[stackIndex];//后进先出
stackIndex--;//元素出栈后,下一个要出栈的元素索引
return data;
}
}
}
泛型函数
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.WriteLine(function<int>(100));
}
static T1 function<T1>(T1 a1)
{
return a1;
}
}
-------------------------------------------------------------------------------
public T add<T,T1,T2>(T1 a,T2 b)where T : struct, T1, T2
{
dynamic a1 = a;
dynamic b1 = b;
return a1 + b1;
}
用 default 来完成 模板类的 泛型变量 的初始化
public class MyGenericClass<T1, T2>
{
private T1 data1;
private T2 data2;
public MyGenericClass()
{
//data1 = new T1();
//data1 = null; //因为 T1 类型不是引用类型,需要用不了 new 和 null
//但是可以使用 default 来完成初始化
data1 = default(T1);
data2 = default(T2);
}
}
泛型约束
public class MyGenericClass<T1, T2, T3>
where T1 : struct //T1:表示值类型
where T2 : class //T2:表示引用类型
where T3 : new() //T3:表示一个类中,必须有一个无参的构造方法,这个约束必须放到最后
//其他还有:基类类型、接口类型。。。
{
public List<T2> CourseList { get; set; }
public T3 Publisher { get; set; }
public MyGenericClass()
{
this.CourseList = new List<T2>();
Publisher = new T3();
}
}
dynamic 动态类型的使用
List<string> CourceList=new List<string>();
public T2 BuyCourse<T1,T2>(T1 index)
{
dynamic _index = index; //dynamic是在运行的时候解析对象类型,编译阶段不解析
return CourceList[_index];
}
七、委托、匿名方法、Lambda表达式
委托与事件的区别
委托-----函数指针
具体的,就是可以对函数指针的封装,加了个+=的运算符重载
就相当于函数指针的一个list
using System;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
new A().Test();
Console.ReadLine();
}
class A
{
public void Test()
{
B b = new B();
//[4] 关联委托方法
//b.didi += execute;
b.didi = execute;
b.test();
}
//[2] 方法编写
void execute()
{
Console.WriteLine("execute...");
}
}
class B
{
//[1] 声明委托
public delegate void A();
//[3] 创建委托方法
public A didi;
public void test()
{
//[5] 调用
didi.Invoke();
didi();
}
}
}
}
事件,对委托又进行了一次封装
就是说,事件没有 event = null;的这种操作;没有 event.Invoke() 的操作
委托 -> 匿名方法 -> Lambda表达式
例子1:
using System;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
new A().Test();
Console.ReadLine();
}
class A
{
//委托
delegate void myDelegate();
public void Test()
{
//1、用方法名赋值
myDelegate one = execute;
one();
//2、匿名方法
myDelegate two = delegate () { Console.WriteLine("匿名方法"); };
two.Invoke();
//3、Lambad表达式
myDelegate three = () => { Console.WriteLine("Lambad表达式"); };
three();
}
//[2] 方法编写
void execute()
{
Console.WriteLine("有名字的方法");
}
}
}
}
例子2:
/*
* 委托的几种赋值方式
*/
using System;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
Test1();
Test2();
Test3();
Console.ReadLine();
}
//--------------------------------------------------------------------------
//用函数名 赋值 委托
public static void Test1()
{
//定义委托变量
Func<int, int, int> cal = Method;
//使用委托变量
int result = cal(10, 15);
Console.WriteLine(result);
}
public static int Method(int a,int b)
{
return a + b;
}
//--------------------------------------------------------------------------
//用 delegate 定义的匿名方法 赋值 委托
public static void Test2()
{
//定义委托变量
Func<int, int, int> cal = delegate (int a, int b)
{
return a + b;
};
//使用委托变量
int result = cal(10, 15);
Console.WriteLine(result);
}
//--------------------------------------------------------------------------
//用 Lambad表达式 赋值 委托
public static void Test3()
{
//定义委托变量
Func<int, int, int> cal = (int a, int b) =>
{
return a + b;
};
//使用委托变量
int result = cal(10, 15);
Console.WriteLine(result);
}
}
}
泛型委托与Action、Func
自定义的泛型委托:
using System;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
new A().Test();
Console.ReadLine();
}
class A
{
//自定义委托
delegate T myDelegate<T>(T a,T b);
public void Test()
{
//自定义委托
myDelegate<int> one = (int a,int b) => { return a + b; };
Console.WriteLine(one(1,2));
//Action的使用
Action<int,int> two = (int a,int b) => { Console.WriteLine( $"{a},{b}"); };
two(2, 3);
//Func的使用
Func<int, int, int> three = (int a, int b) => { return a + b; };
three.Invoke(10, 200);
}
//[2] 方法编写
void execute()
{
Console.WriteLine("有名字的方法");
}
}
}
}
八、多线程(Thread)
Thread的API (之前的版本,现在用 Task)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private Thread thread = null; //线程
private int counter = 0; //计数器
//
private ManualResetEvent manualResetEvent = new ManualResetEvent(true);
public Form1()
{
InitializeComponent();
}
//启动
private void button1_Click(object sender, EventArgs e)
{
thread = new Thread(() =>
{
while (true)
{
try
{
Thread.Sleep(500);
manualResetEvent.WaitOne();//用于判断是“暂停” 还是 “继续” 线程
this.Invoke(new Action(() =>
{
this.richTextBox1.Text += this.counter++ + ",";
}));
}
catch(Exception ex)
{
MessageBox.Show(ex.Message + "异常位置:" + counter++);
}
}
});
thread.Start();
}
//暂停
private void button2_Click(object sender, EventArgs e)
{
if(thread.ThreadState == System.Threading.ThreadState.WaitSleepJoin)
{
manualResetEvent.Reset();//让线程受阻
}
}
//继续
private void button3_Click(object sender, EventArgs e)
{
if(thread.ThreadState == System.Threading.ThreadState.WaitSleepJoin)
{
manualResetEvent.Set();//允许等待的线程继续进行
}
}
//中断
private void button4_Click(object sender, EventArgs e)
{
thread.Interrupt();
}
//中止
private void button5_Click(object sender, EventArgs e)
{
thread.Abort();
}
//主线程等待子线程的结束
private void button6_Click(object sender, EventArgs e)
{
Thread thread = new Thread(() =>
{
Console.WriteLine("子线程在运行中...");
Thread.Sleep(3000);
Console.WriteLine("子线程结束");
});
thread.Start();
thread.Join();//主线程会等待子线程完成后,再执行
Console.WriteLine("主线程执行完毕");
}
}
}
是通过给API 传入委托类型的参数来实现的
using System;
using System.Threading;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
//用函数名来给委托赋值
Thread thread1 = new Thread(TStart);
//用匿名函数给委托赋值
Thread thread2 = new Thread(delegate ()
{
Console.WriteLine("线程启动... 2");
});
//用Lambda表达式给委托赋值
Thread thread3 = new Thread(() =>
{
Console.WriteLine("线程启动... 3");
});
//启动
thread1.Start();
thread2.Start();
thread3.Start();
Console.ReadLine();
}
static void TStart()
{
Console.WriteLine("线程启动... 1");
}
}
}
一个简单的例子:
using System;
using System.Threading;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
Thread thread = new Thread(() =>
{
Console.WriteLine("线程启动...");
});
thread.IsBackground = true;//将其设置为后台线程
thread.Start();//启动
Console.WriteLine("这里是主线程的输出");
Console.ReadLine();
}
}
}
线程的开销(空间、时间)
在子线程里完成对主线程控件的操作(Invoke / BeginInvoke / InvokeRequired)
Invoke 阻塞
BeginInvoke 非阻塞
InvokeRequired 检查当前显示是否为子线程
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//阻塞的
void ThreadTestFunction1()
{
Thread thread = new Thread(() =>
{
this.label1.Invoke(new Action<string>(data =>
{
Thread.Sleep(3000);
this.label1.Text = data;
}), "200");
Console.WriteLine("111111111111");
});
thread.Start();
}
//非阻塞的
void ThreadTestFunction2()
{
Thread thread = new Thread(() =>
{
this.label2.BeginInvoke(new Action<string>(data =>
{
Thread.Sleep(3000);
this.label2.Text = data;
}), "201");
Console.WriteLine("22222222222222");
});
thread.Start();
}
//子线程和主线程都可以调用的方法
void ThreadTestFunction3()
{
if (this.label3.InvokeRequired) //如果是子线程访问
{
//this.label3.Invoke(new Action<string>(data =>
//{
// this.label3.Text = data;
//}),"900");
this.label3.Invoke(new Action<string>(data =>
{
this.label3.Text = data;
}), "900");
}
else //如果是父线程访问
{
this.label3.Text = "901";
}
}
private void button1_Click(object sender, EventArgs e)
{
ThreadTestFunction1();
}
private void button2_Click(object sender, EventArgs e)
{
ThreadTestFunction2();
}
private void button3_Click(object sender, EventArgs e)
{
ThreadTestFunction3();
}
}
}
之前版本的线程池(ThreadPool.QueueUserWorkItem)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
//TestThreadPoolFunction1();
//TestThreadPoolFunction2();
TestThreadPoolFunction3();
Console.ReadLine();
}
static void TestThreadPoolFunction1()
{
ThreadPool.QueueUserWorkItem(x=>
{
Console.WriteLine("子线程:" + Thread.CurrentThread.ManagedThreadId);
},"116");
Console.WriteLine("主线程:" + Thread.CurrentThread.ManagedThreadId);
}
static void TestThreadPoolFunction2()
{
ThreadPool.QueueUserWorkItem(x =>
{
Console.WriteLine("子线程:" + Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("传入线程的参数为:" + x);
}, "116");
Console.WriteLine("主线程:" + Thread.CurrentThread.ManagedThreadId);
}
static void TestThreadPoolFunction3()
{
for(int i = 0; i < 10; ++i)
{
ThreadPool.QueueUserWorkItem(x =>
{
Console.WriteLine(string.Format("子线程:{0},传入线程的参数为:{1}", Thread.CurrentThread.ManagedThreadId,x));
Thread.Sleep(50);
}, i);
Console.WriteLine("主线程:" + Thread.CurrentThread.ManagedThreadId);
}
}
}
}
九、多线程(Task)
开启的三种方式
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
//方式一:先创建对象,再开启线程
Task task1 = new Task(() =>
{
Console.WriteLine("线程ID:" + Thread.CurrentThread.ManagedThreadId);
});
task1.Start();
//方式二、三:在创建的地方开启线程
Task.Run(() =>
{
Console.WriteLine("线程ID:" + Thread.CurrentThread.ManagedThreadId);
});
Task.Factory.StartNew(() =>
{
Console.WriteLine("线程ID:" + Thread.CurrentThread.ManagedThreadId);
});
Console.ReadLine();
}
}
}
终止 / 重启(用信号源对线程进行控制)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//取消任务信号源
private CancellationTokenSource cts = new CancellationTokenSource();
//启动线程
private void button1_Click(object sender, EventArgs e)
{
if (cts.IsCancellationRequested)//之前的信号源被取消了,则更换一个新的信号源
{
cts = new CancellationTokenSource();
}
Task.Run(() =>
{
int counter = 0;
while (!cts.IsCancellationRequested)
{
counter++;
Thread.Sleep(1000);
Console.WriteLine(counter);
}
}, cts.Token);
}
//停止线程
private void button2_Click(object sender, EventArgs e)
{
cts.Cancel();//调用这个方法,线程就可以停止执行了
}
}
}
暂停 / 继续 (用时间对象对线程进行控制)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Task.Run(() =>
{
int counter = 0;
while (true)
{
mResetEvent.WaitOne();//用来控制暂停和继续
counter++;
Thread.Sleep(1000);
Console.WriteLine(counter);
}
});
}
//手动停止事件对象
private ManualResetEvent mResetEvent = new ManualResetEvent(true);
//启动线程
private void button1_Click(object sender, EventArgs e)
{
mResetEvent.Set();//继续
}
//停止线程
private void button2_Click(object sender, EventArgs e)
{
mResetEvent.Reset();//暂停
}
}
}
执行一段时间后停止
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
//用于控制线程
private CancellationTokenSource cts = new CancellationTokenSource();
public Form1()
{
InitializeComponent();
Task task = new Task(() =>
{
int counter = 0;
while (!cts.IsCancellationRequested)
{
counter++;
Thread.Sleep(1000);
Console.WriteLine(counter);
}
}, cts.Token);
//线程开启 3 秒后结束线程
cts.CancelAfter(3000);
//开启线程
task.Start();
}
}
}
执行完后,执行回调函数
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
//用于控制线程
private CancellationTokenSource cts = new CancellationTokenSource();
public Form1()
{
InitializeComponent();
Task task = new Task(() =>
{
Console.WriteLine("线程进行中 1");
Thread.Sleep(1000);
Console.WriteLine("线程进行中 2");
Thread.Sleep(1000);
Console.WriteLine("线程进行中 3");
Thread.Sleep(1000);
cts.Cancel();//执行这个(或者这个 CancelAfter),才会去执行,结束的回调(Register)
}, cts.Token);
cts.Token.Register(() =>
{
Console.WriteLine("线程结束了");
});
//开启线程
task.Start();
}
}
}
执行多个或者多个的一个后执行回调线程(API:ContinueWith)
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Task task1 = new Task(() =>
{
Thread.Sleep(1000);
Console.WriteLine("task1,线程号:"+Thread.CurrentThread.ManagedThreadId);
});
Task task2 = new Task(() =>
{
Thread.Sleep(2000);
Console.WriteLine("task2,线程号:" + Thread.CurrentThread.ManagedThreadId);
});
Task task3 = new Task(() =>
{
Thread.Sleep(3000);
Console.WriteLine("task3,线程号:" + Thread.CurrentThread.ManagedThreadId);
});
task1.Start();
task2.Start();
task3.Start();
//或者:Task.WaitAny(task1, task2, task3).CiontinueWith(...)
Task.WhenAll(task1, task2, task3).ContinueWith(t =>
{
Thread.Sleep(1000);
Console.WriteLine("后面开启的线程:" + Thread.CurrentThread.ManagedThreadId);
});
Console.WriteLine("主线程,线程号:"+Thread.CurrentThread.ManagedThreadId);
}
}
}
主线程等待子线程的三种API:
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Task task1 = new Task(() =>
{
Thread.Sleep(1000);
Console.WriteLine("task1,线程号:"+Thread.CurrentThread.ManagedThreadId);
});
Task task2 = new Task(() =>
{
Thread.Sleep(2000);
Console.WriteLine("task2,线程号:" + Thread.CurrentThread.ManagedThreadId);
});
Task task3 = new Task(() =>
{
Thread.Sleep(3000);
Console.WriteLine("task3,线程号:" + Thread.CurrentThread.ManagedThreadId);
});
task1.Start();
task2.Start();
task3.Start();
//第一种阻塞方式
//task1.Wait();
//task2.Wait();
//task3.Wait();
//第二种阻塞方式
//Task.WaitAll(task1, task2, task3);
//第三种阻塞方式
Task.WaitAny(task1, task2, task3);
Console.WriteLine("主线程,线程号:"+Thread.CurrentThread.ManagedThreadId);
}
}
}
-----------------------------
跨线程访问(在子线程中,去操作主线程中的内容)
就是在开启线程的地方添加一个入参
TaskScheduler.FromCurrentSynchronizationContext()
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//卡顿
private void button1_Click(object sender, EventArgs e)
{
Task task = new Task(() =>
{
Thread.Sleep(3000);//延时操作会卡顿UI
this.label1.Text = "-新的内容";
});
task.Start(TaskScheduler.FromCurrentSynchronizationContext());
}
//不卡顿
private void button2_Click(object sender, EventArgs e)
{
Task task = new Task(() =>
{
Thread.Sleep(3000);//延时操作会卡顿UI
});
task.ContinueWith(t =>
{
this.label1.Text = "新的内容";
}, TaskScheduler.FromCurrentSynchronizationContext());
task.Start();
}
}
}
-------------------------------
锁
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class Program
{
private static readonly Object mylock = new object();
private static int counter = 0;
static void Main(string[] args)
{
Test();
Console.ReadLine();
}
static void Test()
{
for(int i = 0; i < 10;++i)
{
Task.Run(() =>
{
for (int j = 0; j < 100; j++)
{
//lock (this)//静态类里用不了 this
lock (mylock)
{
Console.WriteLine($"id:{Thread.CurrentThread.ManagedThreadId}-couter:{counter++}");
}
}
});
}
}
}
}
十、多线程 (async、await)
据说这个一个语法糖,目的是为了更方便的写异步
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
Test();
Console.WriteLine("这里是主线程的内容..." + ",线程ID:" + Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
async static void Test()
{
await Task.Run(() =>
{
Console.WriteLine("线程开始了"+",线程ID:"+Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(3000);
Console.WriteLine("线程快要结束了" + ",线程ID:" + Thread.CurrentThread.ManagedThreadId);
});
Console.WriteLine("这里是异步回调里执行的内容..." + ",线程ID:" + Thread.CurrentThread.ManagedThreadId);
}
}
}
执行的顺序(打印):
十一、LINQ
模仿 SQL 语句来写内存中的查询
一个简单的例子
/*
* 将一个 int数组中的奇数挑出来,后从小到大排列
*/
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
Test1();
Test2();
Console.ReadLine();
}
static int[] nums = { 1, 6, 9, 3, 7, 38, 16, 68, 42, 99, 33 };
//不使用 LINQ
public static void Test1()
{
List<int> result = new List<int>();
//找到奇数
foreach(int item in nums)
{
if (item % 2 != 0)
{
result.Add(item);
}
}
result.Sort();//排序
result.Reverse();//使之逆序
//打印
foreach (int item in result)
{
Console.Write(item + ",");
}
Console.WriteLine();
}
//使用 LINQ
public static void Test2()
{
var result = from num in nums
where num % 2 != 0
orderby num descending
select num;
//打印
foreach(int item in result)
{
Console.Write(item+",");
}
Console.WriteLine();
}
}
}
原理:
用于拓展方法,和返回泛型接口,写链式编程
扩展方法 查询函数
select 处理(1、改变值, 2、从类中去除需要筛选的元素)
where 过滤
orderBy 升序排列
OrderByDescending 降序排列
GroupBy 分组
Distinct 去除重复元素
/**
* Linq 查询语句
*
*/
/**
* Linq 查询语句
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
Test1();
Test1_1();
Test2();
Test3();
Test4();
Test5();
Test6();
Console.ReadLine();
}
static int[] nums = { 1, 1, 1, 6, 9, 3, 7, 38, 16, 68, 42, 99, 33 };
public class A
{
public int x;
public int y;
public string z;
}
//扩展方法 Select
public static void Test1()
{
var result = nums.Select(x => x * x);
//打印
foreach (int item in result)
{
Console.Write(item + ",");
}
Console.WriteLine();
}
public static void Test1_1()
{
A[] Class_A_Array = { new A() { x = 1 }, new A() { x = 2 }, new A() { x = 3 } };
var result = Class_A_Array.Select(classA => classA.x);
//打印
foreach (int item in result)
{
Console.Write(item + ",");
}
Console.WriteLine();
}
//扩展方法 Where
public static void Test2()
{
var result = nums.Where(x => x < 10);
//打印
foreach (int item in result)
{
Console.Write(item + ",");
}
Console.WriteLine();
}
//扩展方法 OrderBy
public static void Test3()
{
var result = nums.OrderBy((x) => x);
//打印
foreach (int item in result)
{
Console.Write(item + ",");
}
Console.WriteLine();
}
//扩展方法 OrderByDescending
public static void Test4()
{
var result = nums.OrderByDescending(x => x);
//打印
foreach (int item in result)
{
Console.Write(item + ",");
}
Console.WriteLine();
}
//扩展方法 GroupBy
public static void Test5()
{
var result = nums.GroupBy(x => x % 10);//个位数相同的分为一组
//打印
Console.WriteLine("--------------------------");
foreach (var items in result)
{
foreach (int item in items)
{
Console.Write(item + ",");
}
Console.WriteLine();
}
Console.WriteLine("--------------------------");
}
//扩展方法 OrderByDescending
public static void Test6()
{
var result = nums.Distinct();
//打印
foreach (int item in result)
{
Console.Write(item + ",");
}
Console.WriteLine();
}
}
}
<查询语句> 混合 <扩展方法> 的写法
查询语句一种,更方便调用 扩展方法 的写法
但是有些 查询语句没有对应的 查询语句的写法,所以有的时候需要混合起来写
Count 计数
/**
* 聚合函数 count
*/
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
internal class Program
{
public class A
{
public int x;
public int y;
public string z;
}
static List<A> list;
static void Main(string[] args)
{
//初始化需要 查询的内容
A a1 = new A() { x = 1, y = 1, z = "a" };
A a2 = new A() { x = 2, y = 1, z = "b" };
A a3 = new A() { x = 3, y = 1, z = "c" };
A a4 = new A() { x = 4, y = 1, z = "d" };
A a5 = new A() { x = 5, y = 1, z = "e" };
A a6 = new A() { x = 6, y = 1, z = "f" };
A a7 = new A() { x = 7, y = 1, z = "g" };
list = new List<A>() { a1, a2, a3, a4, a5, a6, a7 };
Test1();
Console.ReadLine();
}
//扩展方法 Count
public static void Test1()
{
var count = (from x in list
where x.x > 3
select x).Count();
//打印
Console.WriteLine($"count:{count}");
}
}
}
聚合函数
Count 计数
Max 找到最大值
Min 找到最小值
Average 计算平均值
Sum 统计总和
/**
* 聚合函数
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
internal class Program
{
public class A
{
public int x;
public int y;
public string z;
}
static List<A> list;
static void Main(string[] args)
{
//初始化需要 查询的内容
A a1 = new A() { x = 1, y = 1, z = "a" };
A a2 = new A() { x = 2, y = 1, z = "b" };
A a3 = new A() { x = 3, y = 1, z = "c" };
A a4 = new A() { x = 4, y = 1, z = "d" };
A a5 = new A() { x = 5, y = 1, z = "e" };
A a6 = new A() { x = 6, y = 1, z = "f" };
A a7 = new A() { x = 7, y = 1, z = "g" };
list = new List<A>() { a1, a2, a3, a4, a5, a6, a7 };
Test1();
Test2();
Console.ReadLine();
}
//扩展方法 Count
public static void Test1()
{
var count = (from x in list
where x.x > 3
select x).Count();
//打印
Console.WriteLine($"count:{count}");
}
//扩展方法 Max Min Average Sum
public static void Test2()
{
var max = (from x in list
select x.x).Max();
var min = (from x in list
select x.x).Min();
var avg = (from x in list
select x.x).Average();
var sum = (from x in list
select x.x).Sum();
//打印
Console.WriteLine($"max:{max}");
Console.WriteLine($"min:{min}");
Console.WriteLine($"avg:{avg}");
Console.WriteLine($"sum:{sum}");
}
}
}
多项 综合排序 的写法
查询语句
orderby
扩展方法
.OrderBy(s=>s.x)
.ThenBy(s=>s.y)
//.ThenBy(s=>s.z);
.ThenByDescending(s=>s.z);
ThenBy:用于在当前排序的基础上进行升序排列。
ThenByDescending:用于在当前排序的基础上进行降序排列。
/**
* 混合排序
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
internal class Program
{
public class A
{
public int x;
public int y;
public string z;
}
static List<A> list;
static void Main(string[] args)
{
//初始化需要 查询的内容
A a11 = new A() { x = 1, y = 2, z = "a" };
A a12 = new A() { x = 1, y = 1, z = "a" };
A a13 = new A() { x = 1, y = 3, z = "c" };
A a14 = new A() { x = 1, y = 3, z = "a" };
A a15 = new A() { x = 1, y = 3, z = "b" };
A a2 = new A() { x = 6, y = 3, z = "b" };
A a3 = new A() { x = 7, y = 2, z = "c" };
A a4 = new A() { x = 4, y = 1, z = "d" };
A a5 = new A() { x = 5, y = 5, z = "e" };
A a6 = new A() { x = 2, y = 6, z = "f" };
A a7 = new A() { x = 3, y = 7, z = "g" };
list = new List<A>() { a11, a12, a13, a14, a15, a2, a3, a4, a5, a6, a7 };
Test1();
Test2();
Console.ReadLine();
}
// 查语句的方式
public static void Test1()
{
var newList = from x in list
orderby x.x, x.y
select x;
//打印
Console.WriteLine("-----------------------");
foreach (A a in newList)
{
Console.WriteLine($"{a.x}-{a.y}-{a.z}");
}
}
// 扩展方法的方式
public static void Test2()
{
var newList = list
.Select(s=>s)
.OrderBy(s=>s.x)
.ThenBy(s=>s.y)
//.ThenBy(s=>s.z);
.ThenByDescending(s=>s.z);
//打印
Console.WriteLine("-----------------------");
foreach (A a in newList)
{
Console.WriteLine($"{a.x}-{a.y}-{a.z}");
}
}
}
}
创建集合
Range 按一个范围生成
Repeat 生成重复的
/**
* 创建序列
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
Test1();
Console.ReadLine();
}
//
public static void Test1()
{
var nums1 = Enumerable.Range(0, 10);
var nums2 = Enumerable.Repeat("asd", 10);
//打印
Console.WriteLine("-----------------------");
foreach (var a in nums1)
{
Console.WriteLine(a);
}
Console.WriteLine("-----------------------");
foreach (var a in nums2)
{
Console.WriteLine(a);
}
}
}
}
十二、其他
0、网站
https://sharplab.io/
1、带同步机制的方法:
2、计时操作
var sw = Stopwatch.StartNew();
Thread.Sleep(100);
Console.WriteLine($"Elapsed time : {sw.ElapsedMilliseconds}ms");
3、使用方法实现并行计算
//for(int i = 0; i < inputs.Length; i++)
//{
// outputs[i] = HeavyJob(inputs[i]);
//}
//Parallel.For(0, inputs.Length, i => outputs[i] = HeavyJob(inputs[i]));
//outputs = inputs.AsParallel().Select(x => HeavyJob(x)).ToArray();
outputs = inputs.AsParallel().AsOrdered().Select(x => HeavyJob(x)).ToArray();