一、结构与类
function a(out int x){
x=12;
return x;
}
int b;
a(out b);
此时b为12
public car (string description):this(description ,4));
public car(string description,int a);
8、C#对象 new出来后一般都为强引用,可以使用weakReference设置为弱引用,当GC垃圾回收期运行时进行对象的回收,因此使用时需要用isAlive判断是否存在
IDisplay<Shape>
IDisplay<Rectangle>
泛型接口定义In时,输入只能为T 为抗变,输出可以转化为基类
二、泛型、数组、运算符转化
1、泛型结构:可空类型 ? 表示可空类型是一种典型的泛型结构,int? x1
可空与非空转化
int ?x1;
...
int y1=x1??0 //为空则为0
2、数组 为引用类型在堆上,事先不知道元素个数的话建议使用集合
3、不知道数组类型时,可以使用createInstance来创建
4、使用sort需要实现IComparable接口,接口只有一个compare方法
5、arr.clone方法
①值类型:复制所有值
②引用类型:复制引用
6、foreach使用IEnumerator迭代集合中元素,接口主要有一个current表示当前位置,moveNext()移到下一个
C#把foreach解析为IEnumeable接口的方法和属性
获得IEnumerator的方法:
IEnumerator <person> enumerator = persons.GetEnumrator()//获得枚举器
yield return 返回->移动 实现了一个枚举器
foreach默认使用GetENumeartor()等价于
foreach(var title in titles.getEnumerator())
7、结构比较 IStructuralEqutable, IStructComparable, 前者用于比较内容,后者用于进行排序
Equals(Object o ,IEquality e)
e实现IEqualityComparer<T>接口
(person ) as IStructuralEqutable.Equals(person2,EqualityConparer<Person> Default)
8、c#默认unchecked禁止溢出检查,可以使用checked代码块进行溢出检查
9、as 引用类型显示转换,如果不兼容 返回null
10、sizeof确定栈中需要长度 (单位字节) int 为4
11、可空类型比较中如果有一个为null就为false
12、int强制转换成char时,转化为ASCII码为int的字符
13、装箱、拆箱 :把值类型转换为引用类型为装箱,创建引用类型的箱子
14、比较引用类型的4中方法
①、ReferenceEquals() 是否引用一个实例,Object的静态方法,值类型返回false null=null
②、Equals 静态 不必处理null
③、Equals动态 需要处理null,自定义
④、== 可以重载 默认与①相同
15、C#支持运算符重载,java要写函数才行
operator关键字告诉编译器是一个重载函数
public static vector operator +(vector rhs,vector rhs)
public static为要求的参数
重载==必须重载!=否则编译错误,还需重载Equals和GetHashCode()
16、自定义类型转换 implicit隐式 exolicit显式
17、类强制转换 ①、不能有派生关系 ②、只能在目标内部丁意思
三、委托、lambda表达式和事件
委托:
delegate void IntMethodInvoker(int x);
定义时必须给出签名以及返回类型
GetAString a = x.tostring
GetAString a = new GetAString(x.tostring)
6、委托是为了什么?目前的理解是为了传递函数,函数作参数,定义委托后,可以把函数当做变量使用,传入参数之后,在方法内进行调用
委托的冒泡排序
static public void Sort<T> (Ilist<T> sortArray,Func<T,T,bool> compaison)
10、多播委托
Action<double> operation 1 = fun1;
Action<double> operation 2 = fun2;
Action<double> opearyions = fun1+fun2;
Action<double> operations = fun1;
operations+=fun2
本质是派生自MulticastDelegate的类,把多个方法调用链接为一个列表
Problem:①、方法链的顺序并未正式定义——避免编写依赖于特定顺序调用方法的代码
②、一个方法抛出异常,整个迭代都停止——Delegate的GetInvocationLis()方法返回一个Delegate数组
Action d1 = fun1;
d1+ = fun2;
Delegate[] delegates = d1.GetInvocationList();
foreach(Action d in delegates){
try{
d();
}
catch(Exception)
{
...
}
}
此时就算报错也会继续迭代
11、匿名方法:把代码传递给委托,而不是方法 Tips:①可以使用方法级的参数,②不能使用跳转语句break,goto,continue跳转出匿名方法,也不能跳转进去②不能访问不安全的代码,不能访问ref和out 的参数,3.0开始使用lambda表达式替代匿名方法
Func<string,string> a = delegate(string a ){...}
param为传入参数,右侧为实现代码
参数:
①一个参数 ,写出参数名
Func<string,string> lambda = param=>
{
....
}
②多个参数
Func<double,double,double> twoparams = (double x,double y) =>x*y
最好为参数加上类型,如果只有条语句,可以不需要{}和return,编译器自动加return
闭包:
lambda表达式可以访问块外部的变量称为闭包
lambda表达式创建一个匿名类,有一个构造函数传递外部变量,
使用foreach语句的闭包,C#5.0改变,
5.0之前使用的是外部变量,是在调用时,而不是迭代时获得val变量的值(就是第一次循环之后val为30,因为没有传入局部变量)需要定义个局部变量传入到lambda表达式中
5.0后不需要了foreach创建while循环式,会创建一个局部循环变量
var values = new list<int>() {10,20,30};
var funs = new list<Func<int>>();
foreach(var val in values){
funs.Add(()=>val);
}
foreach(var f in funs){
Console.WriteLine((f()));
}
5.0前输出3次30,5.0之后输出10,20,30
事件
事件为委托提供发布/订阅机制
class Program
{
static void Main(string[] args)
{
var dealer = new Dealer();
var michael = new Consumer("michal");
dealer.NewInfo += michael.NewInfoIsHere;
//也可以通过-=取消订阅
}
}
/// <summary>
///
/// </summary>
public class InfoEventArgs : EventArgs
{
public InfoEventArgs(string car)
{
this.info = info;
}
public string info { get;private set }
}
public class Dealer{
public event EventHandler<InfoEventArgs> NewInfo;
//定义事件 EventHandler<TEventArgs>定义一个处理程序,返回void 带2个参数 ,第一个参数是对象(发送者),第二个T提供相关信息约束继承自EventArgs
//public delegate void EventHandler<TEventArgs>(object sender,TEventArgs e) where TEventArgs:EventArgs 长标记表示。
public void InfoNew(string info)
{
RaiseNewInfo(info);
}
protected virtual void RaiseNewInfo(string info)
{
EventHandler<InfoEventArgs> newINFO = NewInfo;
if(newINFO!=null){
newINFO(this,new InfoEventArgs(info));//这其实是一个委托=>michal.NeWInfoIsHere(this,new InfoEventArgs(info));
}
}
}
public class Consumer{
private string name;
public Consumer(string name ){
this.name = name;
}
public void NewInfoIsHere(object sender, InfoEventArgs e)
{
Console.WriteLine("{0} : car {1} is new",name ,e.info);
}
}
在发布者类中定义事件(本质是一个带2个参数的委托),通过eventArgs传递参数
在订阅者类中编写符合委托的方法,并且与发布者类事件绑定实现订阅
①发布者类事件发生(某个方法调用)->②发布者类调用事件绑定的委托(委托通过+=绑定了订阅者的事件) 期间发布者类new一个实现eventArgs接口的类传递参数。
弱事件:WeakEventManager 存在的理由:当侦听器不在直接引用,发布程序仍会保存一个引用,因此GC不能情况侦听器占用的内存。一种方法是确保对事件取消订阅,另外一种就是WeakEventManager
需要创建一个派生自WeakEventManager 的类作为弱事件管理器来管理发布程序和侦听器的连接
Addlistener与removelistemer实现了侦听器的添加删除
startlistening和stoplistening添加第一个时以及删除最后一个时会调用
侦听器实现IWeakEventListener借楼,实现ReceiveWeakEvent方法,触发事件时,弱事件管理器调用这个方法
public class WeakInfoEventManager:WeakEventManager{
/// <summary>
///实现弱事件管理器类的单例
/// </summary>
public static void Addlistener(object source,IWeakEventListener listener)
{
CurrentManager.ProtectedAddListener(source,listener);
}
public static void Removelistener(object source,IWeakEventListener listener)
{
CurrentManager.ProtectedRemoveListener(source,listener);
}
public static WeakEventManager CurrentManager{
get{
var manager = GetCurrentManager(typeof(WeakInfoEventManager)) as WeakInfoEventManager;
if(manager == null)
{
manager = new WeakInfoEventManager();
SetCurrentManager(typeof(WeakInfoEventManager),manager);
}
return manager;
}
}
/// <summary>
/// 静态方法连接发布程序
/// </summary>
/// <param name="source"></param>
protected override void StartListening(object source)
{
(source as Dealer).NewInfo += Deal_NewInfo;
}
void Deal_NewInfo(object sender,InfoEventArgs e){
DeliverEvent(sender,e);
}
protected override void StopListening(object source)
{
(source as Dealer).NewInfo -= Deal_NewInfo;
}
}
public class Consumer:IWeakEventListener{
private string name;
public Consumer(string name ){
this.name = name;
}
public void NewInfoIsHere(object sender, InfoEventArgs e)
{
Console.WriteLine("{0} : car {1} is new",name ,e.info);
}
bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e) {
NewInfoIsHere(sender, e as InfoEventArgs);
return true;
}
}
.net4.5 实现弱事件管理器泛型
WeakEventManager<TEventSource,TEventArgs>派生自基类WeakEventManager,不需要为每个事件实现自定义弱事件管理器,不需要侦听器实现接口IWeakEventsListener,只需要订阅和取消事件
WeakEventManager<Dealer, InfoEventArgs>.AddHandler(dealer, "(NewInfo)事件名称", michael.NewInfoIsHere);
WeakEventManager<Dealer, InfoEventArgs>.RemoveHandler(dealer, "(NewInfo)事件名称", michael.NewInfoIsHere);
我们会在开发Windows应用程序时大量使用委托和时间来监控应用程序执行时出现的Windows消息方式,在设计大型应用时可以减少依赖性和层的耦合,开发可重用的组件