1. 值类型和引用类型的相同点:
- 引用类型可以实现接口,值类型当中的结构体也可以实现接口;
- 引用类型和值类型都继承自System.Object类。
2. 值类型和引用类型的区别:
- 1)范围方面
C#的值类型包括:结构体(数值类型、bool型、用户定义的结构体),枚举,可空类型。
C#的引用类型包括:数组,用户定义的类、接口、委托,object,字符串。- 2)内存分配方面:
数组的元素不管是引用类型还是值类型,都存储在托管堆上。
引用类型在栈中存储一个引用,其实际的存储位置位于托管堆。简称引类型部署在托管推上;
而值类型总是分配在它声明的地方:作为字段时,跟随其所属的变量(实 例)存储;作为局部变量时,存储在栈上。(栈的内存是自动释放的,堆内存是.NET中会由GC来自动释放)- 3)适用场合
值类型在内存管理方面具有更好的效率,并且不支持多态,适合用做存储数据的载体;引用类型支持多态,适合用于定义应用程序的行为。
引用类型可以派生出新的类型,而值类型不能,因为所有的值类型都是密封(seal)的;
引用类型可以包含null值,值类型不能(可空类型功能允许将 null 赋给值类型,如 int? a = null; );
引用类型变量的赋值只复制对对象的引用,而不复制对象本身。而将一个值类型变量赋给另一个值类型变量时,将复制包含的值。
using System;
namespace InterfaceTest
{
internal class Program
{
public static void Main(string[] args)
{
Calculator calculator = new Calculator();
Action action = new Action(calculator.Report);//Action委托
calculator.Report();//直接调用
action.Invoke();//间接调用
action();//间接调用
}
}
class Calculator
{
public void Report()
{
System.Console.WriteLine("I have 3 methods");
}
public int Sum(int a, int b)
{
return a + b;
}
}
}
using System;
namespace InterfaceTest
{
internal class Program
{
public static void Main(string[] args)
{
Calculator calculator = new Calculator();
Func<int, int, int> func = new Func<int, int, int>(calculator.Sum);//func<>委托
calculator.Sum(2, 3);//直接调用
func.Invoke(2, 3);//间接调用
func(2, 3); //间接调用
}
}
class Calculator
{
public void Report()
{
System.Console.WriteLine("I have 3 methods");
}
public int Sum(int a, int b)
{
return a + b;
}
}
}
using System;
namespace InterfaceTest
{
public delegate double Cal(double x, double y);//委托声明
class Program
{
static void Main(string[] args)
{
Calculator calculator = new Calculator();
Cal cal = new Cal(calculator.Sum);//委托实例化,方式一
Cal cal1 = calculator.Sub;//委托实例化,方式二
System.Console.WriteLine(cal(3, 2));
System.Console.WriteLine(cal1(3, 2));
}
}
class Calculator
{
public void Report()
{
System.Console.WriteLine("I have 3 methods");
}
public double Sum(double a, double b)
{
return a + b;
}
public double Sub(double a, double b)
{
return a - b;
}
}
}
using System;
namespace InterfaceTest
{
public delegate double Cal(double x, double y);//委托声明
class Program
{
static void Main(string[] args)
{
ProductFactory productFactory = new ProductFactory(); //声明产品方法
WrapFactory wrapFactory = new WrapFactory(); //声明产品封装方法
Func<Product> func1 = new Func<Product>(productFactory.MakePizza);//声明委托方法,获取产品名字信息,并作为产品封装方法的传入参数
Func<Product> func2 = new Func<Product>(productFactory.MakeToCar);
Box box1 = wrapFactory.WrapProduct(func1); //调用产品封装方法,输出含产品名字信息的box类
Box box2 = wrapFactory.WrapProduct(func2);
System.Console.WriteLine(box1.Product.Name); //输出结果
System.Console.WriteLine(box2.Product.Name);
}
}
class Product
{
public string Name { get; set; }
}
class Box
{
public Product Product { get; set; }
}
class WrapFactory
{
//传入委托参数,内部使用委托方法
public Box WrapProduct(Func<Product> getProduct)
{
Box box = new Box();
Product product = getProduct.Invoke();//调用委托方法,即所传入委托参数的成员类型
box.Product = product;
return box;
}
}
class ProductFactory
{
public Product MakePizza()
{
Product product = new Product();
product.Name = "Pizza";
return product;
}
public Product MakeToCar()
{
Product product = new Product();
product.Name = "MakeToCar";
return product;
}
}
}
using System;
namespace InterfaceTest
{
public delegate double Cal(double x, double y);//委托声明
class Program
{
static void Main(string[] args)
{
ProductFactory productFactory = new ProductFactory(); //声明产品方法
WrapFactory wrapFactory = new WrapFactory(); //声明产品封装方法
Func<Product> func1 = new Func<Product>(productFactory.MakePizza);//声明委托方法,获取产品名字信息,并作为产品封装方法的传入参数
Func<Product> func2 = new Func<Product>(productFactory.MakeToCar);
Logger logger = new Logger(); //声明产品记录方法
Action<Product> log = new Action<Product>(logger.Log);
Box box1 = wrapFactory.WrapProduct(func1, log); //调用产品封装方法,输出含产品名字信息的box类
Box box2 = wrapFactory.WrapProduct(func2, log);
System.Console.WriteLine(box1.Product.Name); //输出结果
System.Console.WriteLine(box2.Product.Name);
}
}
//定义记录产品信息类
class Logger
{
public void Log(Product product)
{
System.Console.WriteLine("Product'{0}' create at {1} Price is {2}.", product.Name, DateTime.UtcNow, product.Price); //utcNow为不带时区的时间形式
}
}
class Product
{
public string Name { get; set; }
public double Price { get; set; }
}
class Box
{
public Product Product { get; set; }
}
class WrapFactory
{
//传入委托参数,内部使用委托方法
public Box WrapProduct(Func<Product> getProduct, Action<Product> logCallBack)
{
Box box = new Box();
Product product = getProduct.Invoke();//调用委托方法,即所传入委托参数的成员类型
if (product.Price > 50)
{
logCallBack.Invoke(product);
}
box.Product = product;
return box;
}
}
class ProductFactory
{
public Product MakePizza()
{
Product product = new Product();
product.Name = "Pizza";
product.Price = 12;
return product;
}
public Product MakeToCar()
{
Product product = new Product();
product.Name = "MakeToCar";
product.Price = 100;
return product;
}
}
}
1. 模板方法与回调方法的区别:
- 模板方法:
1)相当于“填空题”;
2)常位于代码中部;
3)委托有返回值- 回调方法:
1)相当于“流水线”;
2)常位于代码末尾;
3)委托无返回值
2. 委托不足(使用需注意,避免滥用,后果严重)
- 1)是方法级别的紧耦合,工作使用要慎重;
- 2)会使代码可读性下降,debug的难度增加;
- 3)把委托回调、异步调用和多线程纠缠在一起,会让代码变得难以阅读和维护;
- 4)委托使用不当会造成内存泄漏和程序性能下降
using System;
using System.Threading;
namespace InterfaceTest
{
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };
Action action1 = new Action(stu1.DoHomework);
Action action2 = new Action(stu2.DoHomework);
Action action3 = new Action(stu3.DoHomework);
action1.Invoke(); //单播委托
action2.Invoke();
action3.Invoke();
}
}
class Student
{
public int ID { get; set; }
public ConsoleColor PenColor { get; set; }
public void DoHomework()
{
for (int i = 0; i < 3; i++)
{
Console.ForegroundColor = this.PenColor;
Console.WriteLine("Student {0} doing homework {1} hours", this.ID, i);
Thread.Sleep(1000);
}
}
}
}
using System;
using System.Threading;
namespace InterfaceTest
{
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };
Action action1 = new Action(stu1.DoHomework);
Action action2 = new Action(stu2.DoHomework);
Action action3 = new Action(stu3.DoHomework);
action1 += action2; //多播委托
action1 += action3;
action1.Invoke();
}
}
class Student
{
public int ID { get; set; }
public ConsoleColor PenColor { get; set; }
public void DoHomework()
{
for (int i = 0; i < 3; i++)
{
Console.ForegroundColor = this.PenColor;
Console.WriteLine("Student {0} doing homework {1} hours", this.ID, i);
Thread.Sleep(1000);
}
}
}
}
【输出结果】- 同上
using System;
using System.Threading;
namespace InterfaceTest
{
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };
stu1.DoHomework(); //直接调用
stu2.DoHomework();
stu3.DoHomework();
for (int i = 0; i < 5; i++)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Main hread {0}", i);
Thread.Sleep(1000);
}
}
}
class Student
{
public int ID { get; set; }
public ConsoleColor PenColor { get; set; }
public void DoHomework()
{
for (int i = 0; i < 3; i++)
{
Console.ForegroundColor = this.PenColor;
Console.WriteLine("Student {0} doing homework {1} hours", this.ID, i);
Thread.Sleep(1000);
}
}
}
}
using System;
using System.Threading;
namespace InterfaceTest
{
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };
Action action1 = new Action(stu1.DoHomework); //委托间接调用
Action action2 = new Action(stu2.DoHomework);
Action action3 = new Action(stu3.DoHomework);
action1();
action2();
action3();
for (int i = 0; i < 5; i++)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Main hread {0}", i);
Thread.Sleep(1000);
}
}
}
class Student
{
public int ID { get; set; }
public ConsoleColor PenColor { get; set; }
public void DoHomework()
{
for (int i = 0; i < 3; i++)
{
Console.ForegroundColor = this.PenColor;
Console.WriteLine("Student {0} doing homework {1} hours", this.ID, i);
Thread.Sleep(1000);
}
}
}
}
【输出结果】- 同上
using System;
using System.Threading;
namespace InterfaceTest
{
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };
Action action1 = new Action(stu1.DoHomework); //委托间接调用
Action action2 = new Action(stu2.DoHomework);
Action action3 = new Action(stu3.DoHomework);
action1.BeginInvoke(null, null); //委托隐式异步调用
action2.BeginInvoke(null, null);
action3.BeginInvoke(null, null);
for (int i = 0; i < 5; i++)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Main thread {0}", i);
Thread.Sleep(1000);
}
}
}
class Student
{
public int ID { get; set; }
public ConsoleColor PenColor { get; set; }
public void DoHomework()
{
for (int i = 0; i < 3; i++)
{
Console.ForegroundColor = this.PenColor;
Console.WriteLine("Student {0} doing homework {1} hours", this.ID, i);
Thread.Sleep(1000);
}
}
}
}
using System;
using System.Threading;
namespace InterfaceTest
{
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };
Thread thread1 = new Thread(stu1.DoHomework); //显示异步调用Thread
Thread thread2 = new Thread(stu2.DoHomework);
Thread thread3 = new Thread(stu3.DoHomework);
thread1.Start();
thread2.Start();
thread3.Start();
for (int i = 0; i < 5; i++)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Main thread {0}", i);
Thread.Sleep(1000);
}
}
}
class Student
{
public int ID { get; set; }
public ConsoleColor PenColor { get; set; }
public void DoHomework()
{
for (int i = 0; i < 3; i++)
{
Console.ForegroundColor = this.PenColor;
Console.WriteLine("Student {0} doing homework {1} hours", this.ID, i);
Thread.Sleep(1000);
}
}
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
namespace InterfaceTest
{
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };
Task Task1 = new Task(stu1.DoHomework); //显示异步调用Task
Task Task2 = new Task(stu2.DoHomework);
Task Task3 = new Task(stu3.DoHomework);
Task1.Start();
Task2.Start();
Task3.Start();
for (int i = 0; i < 5; i++)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Main Task {0}", i);
Thread.Sleep(1000);
}
}
}
class Student
{
public int ID { get; set; }
public ConsoleColor PenColor { get; set; }
public void DoHomework()
{
for (int i = 0; i < 3; i++)
{
Console.ForegroundColor = this.PenColor;
Console.WriteLine("Student {0} doing homework {1} hours", this.ID, i);
Thread.Sleep(1000);
}
}
}
}
using System;
namespace InterfaceTest
{
public delegate double Cal(double x, double y);//委托声明
class Program
{
static void Main(string[] args)
{
IProductFactory PizzaFactory = new PizzaFactory(); //接口子类实例化,多态
IProductFactory TocarFactory = new TocarFactory();
WrapFactory wrapFactory = new WrapFactory(); //声明产品封装方法
Box box1 = wrapFactory.WrapProduct(PizzaFactory);
Box box2 = wrapFactory.WrapProduct(TocarFactory);
System.Console.WriteLine(box1.Product.Name); //输出结果
System.Console.WriteLine(box2.Product.Name);
}
}
interface IProductFactory
{
Product Make();
}
class PizzaFactory : IProductFactory
{
public Product Make()
{
Product product = new Product();
product.Name = "Pizza";
return product;
}
}
class TocarFactory : IProductFactory
{
public Product Make()
{
Product product = new Product();
product.Name = "MakeToCar";
return product;
}
}
class Product
{
public string Name { get; set; }
}
class Box
{
public Product Product { get; set; }
}
class WrapFactory
{
public Box WrapProduct(IProductFactory productFactory)
{
Box box = new Box();
Product product = productFactory.Make();
box.Product = product;
return box;
}
}
}
1.同步与异步的简介
- 中英文语言理解的差异
- 同步:你做完了我接着做(在你的基础上,有顺序的)
- 异步:咱两同时做(同步进行,无顺序)
2.同步调用和异步调用的对比
- 每一个运行的程序都是一个进程(process);
- 每个进程可以有一个或多个线程(thread);
- 同步调用是在同一线程内;异步调用时多线程的;
- 串行=>同步=>单线程;并行=>异步=>多线程
3.同步调用 and 异步调用
- 直接同步调用:使用方法名;
- 间接同步调用:使用单播/多播委托的Invoke方法;
- 隐式异步调用:使用委托的BeginInvoke;
- 显示异步调用:使用Thread 或 Task;