=============================Ch18 参数=============================
GetHashCode获取哈希值,每个对象的哈希值都不一样
Ctrl+. 批量重命名变量
引用参数 ref
调用引用参数前不需要赋值,因为方法中会丢弃
输出参数 out
方法返回前,该方法内每个输出参数必须进行赋值
数组参数 params
形参列表中只能有一个,且必须是最后一个
方法定义:
Static int CalculateSum(params int[] intArray)
{
int sum=0;
foreach(var item in intArray)
{
sum+=item;
}
}
方法调用:
int result=CalculateSum(1,2,3);
str.Split(',',';','.');
具名参数
定义方法:
static void printInfo(string name,int age)
{
}
调用:
PrintInfo(name:"Tim",age:34);
提高代码可读性
参数顺序不再受定义方法的参数列表约束
可选参数 方法定义时给与值后调用可以不传入参数
定义方法:
static void printInfo(string name="Tim",int age=34)
{
}
调用:
PrintInfo();
拓展方法 为目标数据类型增加新的方法
方法必须是共有、静态的
第一个形参必须由this修饰
类似语法:LINQ
定义:
static class DoubleExtension
{
public static double Round(this double input,int digits)
{
double result=Math.Round(input,digits);
return result;
}
}
调用:
double x=3.14159;
double y=x.Round(4);
LINQ(System.Linq命名空间)
List<int> myList=new List<int>{1,2,3,4,5};
bool result=myList.All(i=>i>10);//判断集合中元素是否均大于10
//此处All便是扩展方法,存在于Enumerable类中
各种参数使用场景
1.传值参数():参数的默认传递方式
2.输出参数out:用于除返回值外还需要输出的场景
3.引用参数ref:用于需要修改实际参数值的情形
4.数组参数params:简化方法的调用
5.具名参数=:提高代码可读性,参数列表顺序不受约束
6.可选参数[]:参数拥有默认值
7.扩展方法this:为目标数据类型追加方法
=============================Ch19 委托=============================
是C/C++中函数指针的升级版 Action和Func<>
一切皆地址
变量(数据)是内存中存储的值
函数(算法)是内存中存储的一组机器语言指令
Java中没有与委托相对应的功能实体(如C#委托、C++函数指针)
Class Calculator
{
public void Report()
{
Console.WriteLine("0");
}
}
调用:
Calculator calculator=new Calculator();
Action action=new Action(calculator.Report);
cation.Invoke();
cation();
委托是一种类,类是数据类型,所以委托也是一种数据类型
声明位置尽量在命名空间下方
委托一般把方法当做参数传给另一个方法
用法1.模板方法:借用指定的外部方法来产生结果,相当于填空题,常位于代码中部,具有返回值
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 MakePizzal()
{
Product product=new Product();
product.Name="Pizzal";
return product;
}
public Product MakeToyCar()
{
Product product=new Product();
product.Name="ToyCar";
return product;
}
}
主程序调用
ProductFactory productFactory=new ProductFactory();
WrapFactory warpFactory=new WarpFactory();
Func<Product> func1=new Func<Product>(productFactory.MakePizzal);
Func<Product> func2=new Func<Product>(productFactory.MakeToyCar);
Box box1=wrapFactory.WrapProduct(func1);
Box box2=wrapFactory.WrapProduct(func2);
Console.WriteLine(box1.Product.Name);
Console.WriteLine(box2.Product.Name);
用法2:回调方法callback,调用指定的外部方法,相当于流水线,常位于代码末尾,无返回值
class Product
{
public string Name{get;set;}
public double Price{get;set;};
}
class Logger//日志
{
public void Log(Product product)
{
Console.WriteLine("Product'{0}'created at{1}.Price is
{2}.",product.Name,DateTime.UtcNow,product.Price);
}
class Box
{
public Product Product{get;set;}
}
class WrapFactory
{
public Box WrapProduct(Func<Product> getProduct,Action<Product>logCallBack);//模板方法,无返回
值的方法使用Action委托
{
Box box=new Box();
Product product=getProduct.Invoke();//间接调用方法(函数)
if(product.Price>=50)
{
logCallBack(product);
}
box.Product=product;
return box;
}
}
class ProductFactory
{
public Product MakePizzal()
{
Product product=new Product();
product.Name="Pizzal";
product.Price=12;
return product;
}
public Product MakeToyCar()
{
Product product=new Product();
product.Name="ToyCar";
product.Price=100;
return product;
}
}
主程序调用
ProductFactory productFactory=new ProductFactory();
WrapFactory warpFactory=new WarpFactory();
Func<Product> func1=new Func<Product>(productFactory.MakePizzal);
Func<Product> func2=new Func<Product>(productFactory.MakeToyCar);
Logger logger=new Logger();
Action<Product>log=new Action<Product>(logger.Log);
Box box1=wrapFactory.WrapProduct(func1,log);
Box box2=wrapFactory.WrapProduct(func2,log);
Console.WriteLine(box1.Product.Name);
Console.WriteLine(box2.Product.Name);
委托的缺点
1.它是一种方法级别的紧耦合,现实工作中要慎之又慎
2.使可读性下降,debug难度增加
3.把委托回调、异步调用和多线程纠缠在一起,会让代码难以阅读和维护
4.使用不当有可能使内存泄漏和程序性能下降(委托内容不会从内存中自动释放)
高级使用:多播委托,将多个委托合并封装到一个委托中,调用时只调用合并后的一个委托即可顺序执行全部
委托
隐式异步调用
同步:做完一个事再做另一个,串行=同步=单线程
异步:两个任务同时进行(相当于汉语“同时进行”,容易误导),并行=异步=多线程
Action action1=new Action(stu1.DoHomework);
Action action2=new Action(stu2.DoHomework);
Action action3=new Action(stu3.DoHomework);
action1.BeginInvoke(null,null);//开启分支线程执行action1委托
action2.BeginInvoke(null,null);
action3.BeginInvoke(null,null);
使用lock关键字避免多线程之间的资源冲突
显式异步调用
方法1:
Thread thread1=new Thread(new ThreadStart(stu1.DoHomework));
Thread thread2=new Thread(new ThreadStart(stu2.DoHomework));
Thread thread3=new Thread(new ThreadStart(stu3.DoHomework));
thread1.Start();
thread2.Start();
thread3.Start();
方法2:
Task task1=new Task(new Action(stu1.DoHomework));
Task task2=new Task(new Action(stu2.DoHomework));
Task task3=new Task(new Action(stu3.DoHomework));
task1.Start();
task2.Start();
task3.Start();
应该适时地使用接口取代对一些委托的使用
Java完全使用接口取代了委托的功能
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;
}
}
interface IProductFactory
{
Product Make();
}
class PizzaFactory:IProductFactory
{
public Product Make()
{
Product product=new Product();
product.Name="Pizzal";
return product;
}//重构:不改变代码内容,只是调整代码至更合适的位置
}
class ToyCarFactory:IProductFactory
{
public Product Make()
{
Product product=new Product();
product.Name="ToyCar";
return product;
}
}
主程序调用
IProductFactory pizzaFactory=new PizzaFactory();
IProductFactory toycarFactory=new ToyCarFactory();
Box box1=wrapFactory.WrapProduct(pizzaFactory);
Box box2=wrapFactory.WrapProduct(toycarFactory);
Console.WriteLine(box1.Product.Name);
Console.WriteLine(box2.Product.Name);