查缺补漏

一.委托
1.delegate 自然是要和 目的方法有相同的参数。
   delegate要初始化:
   public delegate void  CatchEventHandler
   CatchEventHandler delegate1 = new CatchEventHandler CatchMethod );
或者
   CatchEventHandler delegate1 =  CatchMethod
绑定多个方法时,按顺序执行。
   CatchEventHandler delegate1 =  CatchMethod 第一次赋值,都是用“+”  而不是“+=”
                                      
delegate1+ =  CatchMethod 2;
所以不能
  CatchEventHandler delegate1 = new CatchEventHandler ;
                                      delegate1+ =  CatchMethod X
                                       delegate1+ =  CatchMethod 2;

delegate作为方法的参数时,如同 string,int 类型一样,在具体调用时,把具有相同参数签名的方法名作为参数直接传递就行。get(1,“s”,
CatchMethod +_+
具有相同参数签名的方法,用delegate代替,可以少写switch判断逻辑。(当然是分情况啦)
delegate是类,继承于基类的delegate,可以在定义class的任意位置定义delegate。

2. 不同类间的通信,就可能用到event。为了保留observer的引用。当subject的内容变更时,需要这些引用来执行observer的方法。
    如果不用event持有observer的引用在subject里,那subject里的event的声明换做delegate其实也可以。
    但是delegate的话就需要做访问器了(set,get),而event不需要可以直接使用。
   而且初始化方式不同。
    event:          ClassPer.event1 += new Handler(method);
    delegate:    ClassPer.delegate1 = new Handler(method);

event其实也是特殊的delegate。event 的事件类型就是 delegate,如:
      ①public delegate void  CatchEventHandler();
则  ②public event CatchEventHandler CatchEvent;
①是delegate的定义。②event只是delegate的引用,不是方法没有参数。跟直接的delegate引用声明CatchEventHandler CatchEvent 类似。

3.event其实就是在发生其他类或对象关注的事情时,该类可以通过event通知其他类。

4.event要有效用,必须先绑定(注册)。就是把委托用 += 赋值与event。

5.注册的delegate要先实例化。就是把同delegate具有相同参数签名的 方法名,放在需要实例化的delegate括号里。
    CatchEvent += new CatchEventHandler(CatchMethod)
对象里运用了event的话,这里的方法 CatchMethod,一般都会是其他类或对象的 方法。

6.event可以注册多个delegate(同delegate的多播委托区别?)

7.event要传递参数的话( object sender, EventArgs args),那delegate也 同样咯,同时目的方法也 要相同的参数。
EventArgs 是基类,运用时,一般都是从它继承出来的子类,可以存储数据信息。

8..Net Framework的编码规范: 

委托类型的名称都应该以EventHandler结束。

委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。

事件的命名为 委托去掉 EventHandler之后剩余的部分。 

继承自EventArgs的类型应该以EventArgs结尾。

委托声明原型中的Object类型的参数代表了Subject,也就是监视对象,在本例中是 Heater(热水器)。回调函数(比如Alarm的MakeAlert)可以通过它访问触发事件的对象(Heater)。

EventArgs 对象包含了Observer所感兴趣的数据。

9.可以参考的文章 http://www.cnblogs.com/cntour365/archive/2008/08/29/1279757.html



二.泛型
1.泛型可以说,就是类型已经参数化。泛型类的类型参数,可以用于类成员,field or property。 class

2.泛型类和接口的继承:
①泛型类继承中,父类的类型参数已被实例化,这时子类不一定必须是泛型类;
②父类的类型参数没有被实例化,但来源于子类,也就是说父类和子类都是泛型类,并且二者有相同的类型参数;
总之:父类不拥有泛型了(被实例化),子类可以拥有泛型。父类拥有泛型,则子类肯定有泛型。

3.泛型委托,泛型方法,就是 在委托或方法声明时包含类型参数,()。同时支持在方法或委托的参数里运用类型参数。(T,t)
public delegate void CatchEventHandler(T, t);
public void Catch(T, t);
泛型不可以运用在除方法以外的其他类或接口成员里,但其他成员可以使用同样作为成员的泛型的类型参数。 对照1

4.泛型方法的声明,调用,重载,覆盖(重写)
using System;
using System.Collections.Generic;
using System.Text;

namespace GenericTest
{
 class GenericClass
 {
  //申明一个泛型方法
  public T getvalue(T t)
  {
   return t;
  }

  //调用泛型方法
  //注意:在调用泛型方法时,对泛型方法的类型参数实例化
  public int useMethod()
  {
   return this.getvalue(10);
  }

  //重载getvalue方法
  public int getvalue(int i)
  {
   return i;
  }
 }

 //下面演示覆盖
 //要注意的是,泛型方法被覆盖时,约束被默认继承,不需要重新指定约束关系
 abstract class Parent
 {
  public abstract K TEST(K k, V v) where K : V;
 }

 class Child : Parent
 {
  public override T TEST(T t, S s)
  {
   return t;
  }
 }
}

5.泛型的约束关系,C#中的泛型只支持显示的约束

T:结构                 类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。
T:类                     类型参数必须是引用类型,包括任何类、接口、委托或数组类型。
T:new()               类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。
T:         类型参数必须是指定的基类或派生自指定的基类。
T:     类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。
T:U                       为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。这称为裸类型约束。

①基类约束
class A { public void F1() {} }
class B { public void F2() {} }
class C
where S: A // S继承自A
where T: B // T继承自B
{
 // 可以在类型为S的变量上调用F1,
 // 可以在类型为T的变量上调用F2
}
②接口约束
interface IPrintable { void Print(); }
interface IComparable { int CompareTo(T v);}
interface IKeyProvider { T GetKey(); }
class Dictionary
where K: IComparable
where V: IPrintable, IKeyProvider
{
 // 可以在类型为K的变量上调用CompareTo,
 // 可以在类型为V的变量上调用Print和GetKey
}
③构造器约束
class A { public A() { } }
class B { public B(int i) { } }
class C
where T : new()
{
 //可以在其中使用T t=new T();
}
C c=new C (); //可以,A有无参构造器。 此处编译器会检查A是否具有无参构造函数。 其中A的初始化是用System.Activator.CreateInstance();实现的,反射。
C c=new C(); //错误,B没有无参构造器
④值类型, 引用类型约束
public struct A { }
public class B { }
class C
where T : struct
{
 // T在这里面是一个值类型
}
C c=new C (); //可以,A是一个值类型
C c=new C(); //错误,B是一个引用类型

可以参考的文章 http://blog.csdn.net/fengsky491/archive/2008/04/07/2256414.aspx
                             http://www.cnblogs.com/ottox/archive/2009/03/02/1401307.html

6. 泛型委托  Predicate /Func /Action

Predicate : 定义一组条件,在指定对象中查找是否有符合条件的结果。 用于 Array 和 List;

public delegate bool  Predicate < T > (T obj);

T: 要比较的对象的类型。

obj: 要按照由此委托表示的方法中定义的条件进行比较的对象。

返回值:如果 obj 符合由此委托表示的方法中定义的条件,则为 true;否则为 false

Func<TResult>

封装一个不具有参数但却返回 TResult 参数指定的类型值的方法。

Func(T1 TResult)Func(T1, T2, TResult), Func(T1, T2, T3, TResult), Func(T1, T2, T3, T4 TResult)

封装一个具有一个参数并返回 TResult 参数指定的类型值的方法,没有T2就是封装一个具有参数并....。

Action, Action, Action, Action, Action

封装一个方法,该方法指定数量的参数(如()无参数,(T1)一个参数,以此类推)并且不返回值。这个和Func有相似处,但无返回值而已。

Lambda表达式里,用了return ,则 return 语句需要用{ }括起来。  x => x + 1;     < === >     x => { return x + 1; }

可以参考的文章 http://www.cnblogs.com/dlonghow/archive/2009/03/25/1421413.html


三.特性Attribute / 属性 Property
1.Attribute 本身就是一个类, 是在编译的时候被实例化的,而不是像通常的类那样在运行时候才实例化。必须写在一对方括号里。

2.自定义的Attribute必须直接或者间接继承System.Attribute。所有自定义的特性名称都应该有个Attribute后缀。
如果类型名不含后缀,在引用属性类时,则可能只认含了后缀的,可以用 @ 标识符处理。

3.Attribute用作编译器指令则不受数量限制。
Conditional:起条件编译的作用,只有满足条件,才允许编译器对它的代码进行编译。一般在程序调试的时候使用。
DllImport:用来标记非.NET的函数,表明该方法在一个外部的DLL中定义。
Obsolete:这个属性用来标记当前的方法已经被废弃,不再使用了。

4.[AttriubteUsage(参数设置)],还有三个属性 AllowMultiple, Inherited, ValidOn
AttriubteUsage只能用于 System.Attribute的派生特性类,且该新特性类的 AllowMultiple 默认 为false, Inherited 默认 为true

using System;                          ======>    using System;

 
 
class X: Attribute {...}                          [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]

                                                  class X: Attribute {...}

5.自定义属性类的默认参数,一般都是 定位参数,在属性类的构造函数参数序列里定义。可选的参数也就是 命名参数,在构造函数里赋默认值,在属性类的filed  和 accesstor里定义(set方法)。
没有set方法会报错: Named attribute argument can''t be a read only property
属性AttriubteUsage中,ValidOn是定位参数,AllowMultiple, Inherited是命名参数。

6. 对于编译器来说, 属性目标说明符显示的指明了该属性希望被用于assembly 还是别的。
[assembly: Help("this a do-nothing assembly")]
可选项  * assembly, * module, * type (运用于类的时候可省略),* method, * property, * event, * field, * param, * return

7.在获取属性的时候,t.GetCustomAttributes()
程序集用
Assembly t = Assembly.LoadFrom(assemblyName);

类,方法,域用
Type t = typeof(Anyclass); 与 Type.GetType()的区别是,typeof参数为类名,GetType参数为带namespace的类全名字符串。

8.属性定义后用给自己?? 搞不明白 为啥, 编译时候顺序呢

基础可查看 http://360doc.com/content/081125/07/81764_1995927.html
高级 http://zzk.cnblogs.com/s?w=blog%3Adudu%20Attribute


四.反射 Reflection
1.采用反射技术可以简化工厂的实现。
(1)工厂方法:通过反射可以将需要实现的子类名称传递给工厂方法,这样无须在子类中实现类的实例化。
(2)抽象工厂:使用反射可以减少抽象工厂的子类。
采用反射技术可以简化工厂代码的复杂程度,在.NET项目中,采用反射技术的工厂已经基本代替了工厂方法。
采用反射技术可以极大地简化对象的生成,对以下设计模式的实现也有很大影响。
(1)命令模式:可以采用命令的类型名称作为参数直接获得命令的实例,并且可以动态执行命令。
(2)享元模式:采用反射技术实例化享元可以简化享元工厂。

2.应用程序结构分为应用程序域—程序集—模块—类型—成员几个层次。

3.Process p = Process.GetCurrentProcess();
   assemblyName = p.ProcessName + ".exe";
  Assembly a = Assembly.LoadFrom(assemblyName);
  Type[] mytypes = a.GetTypes();
  Type ht = typeof(HelloWorld);
  Object bj = Activator.CreateInstance(ht);
  Object bjName = Activator.CreateInstance(ht,s);
  MethodInfo [] mif = ht.GetMethods ();
  MethodInfo msayhello = ht.GetMethod("SayHello");
  msayhello.Invoke(obj,null);

4. 关于程序集的反射
反射appDomain 的程序集
foreach (Assembly assem in Appdomain.currentDomain.GetAssemblies())
{
reflector.ReflectOnAssembly(assem) ;
}

运用System.Reflection.Assembly返回一个程序集
• Load(); Load 将引起CLR把策略应用到程序集上,先后在全局程序集缓冲区,应用程序基目录和私有路径下面查找该程序集,如果找不到该程序集系统抛出异常。
• LoadFrom();传递一个程序集文件的路径名(包括扩展名),CLR会载入您指定的这个程序集,传递的这个参数不能包含任何关于版本号的信息,区域性,和公钥信息,如果在指定路径找不到程序集抛出异常。
LoadWithPartialName();    已经废弃。
※Appdomain的Load()方法与Assembly 的静态Load()方法不同。
AppDomain的load 方法是一种实例方法,返回的是一个对程序集的引用,Assembly的静态Load 方法将程序集按值封装发回给发出调用的AppDomain。

5.关于类型的反射
几种获取type对象的方法:
• Type t = typeof(Anyclass); 与 Type.GetType()的区别是,typeof参数为类名,GetType参数为带namespace的类全名字符串。
• Type.GetType( parameter),System.type 参数为字符串类型,该字符串必须指定类型的完整名称(包括其命名空间)   
• System.type 提供了两个实例方法:GetNestedType,GetNestedTypes   
• Syetem.Reflection.Assembly 类型提供的实例方法是:GetType,GetTypes,GetExporedTypes  
• System.Reflection.Moudle 提供了这些实例方法:GetType,GetTypes,FindTypes

6.关于成员的反射
通过type对象的GetMembers 方法取得一个类型的成员。
• 使用的是不带参数的GetMembers,它只返回该类型的公共定义的静态变量和实例成员
• 使用带参数的GetMembers通过参数设置来返回指定的类型成员
BindingFlags bf = BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public;
foreach (MemberInfo mi int t.getmembers(bf))  
{  
    writeline(mi.membertype);
}

7.通过反射创建类型的实例
• System.Activator 的CreateInstance方法。该方法返回新对象的引用。具体使用方法参见msnd  
• System.Activator 的createInstanceFrom 与上一个方法类似,不过需要指定类型及其程序集   
• System.Appdomain 的方法:createInstance,CreateInstanceAndUnwrap,CreateInstranceFrom和CreateInstraceFromAndUnwrap   
• System.type的InvokeMember实例方法:这个方法返回一个与传入参数相符的构造函数,并构造该类型。   
• System.reflection.constructinfo 的Invoke实例方法

8.反射获取接口,只能获取一层,取父接口需要额外调用。继承关系都是如此?

9.反射的性能:
        使用反射来调用类型或者触发方法,或者访问一个字段或者属性时clr 需 要做更多的工作:校验参数,检查权限等等,所以速度是非常慢的。 所以尽量不要使用反射进行编程,对于打算编写一个动态构造类型(晚绑定)的应用程序,可以采取以下的几种方式进行代替:

• 通过类的继承关系。让该类型从一个编译时可知的基础类型派生出来,在运行时生成该类 型的一个实例,将对其的引用放到其基础类型的一个变量中,然后调用该基础类型的虚方法。
• 通过接口实现。在运行时,构建该类型的一个实例,将对其的引用放到其接口类型的一个变量中,然后调用该接口定义的虚方法。
• 通过委托实现。让该类型实现一个方法,其名称和原型都与一个在编译时就已知的委托相符。在运行时先构造该类型的实例,然后在用该方法的对象及名称构造 出该委托的实例,接着通过委托调用你想要的方法。这个方法相对与前面两个方法所作的工作要多一些,效率更低一些 。

  • Type.GetType属于Reflection的一部分,Reflection可以用于动态解析类型。也就是说,即使编译开发期间没有建立对 Assembly的引用,Type.GetType一样可以用于取得类型信息(相反,typeof是静态解析类型的,所以要求reference)。 如果你理解Namespace和Assembly的关系的话,就会明白单从类型的名称(包括Namespace部分)是不可能找到类型定义的,还必须知道 定义类型的Assembly的名称和位置。所以在调用Type.GetType的时候必须要附带指明Assembly的信息。  
  • 但我想不通了   为什么他们的实例GetType就可以呢???   Object.GetType的工作方式和上面的不同。因为你已经得到了对象实例(object),也就意味着在这之前你已经通过某种方式把定义对象的Assembly加载捣内存里了,不需要额外的信息来确定定义类型的Assembly。

可以参考 http://www.cnblogs.com/yinhu435/archive/2009/09/29/1576524.html

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12913851/viewspace-617708/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/12913851/viewspace-617708/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值