委托和事件示例

C#中委托和事件的例子比较多,讲得好的非常好,就不瞎凑热闹了,推荐博客园大牛的一篇: C# 中的委托和事件 ,如果你已经有了相应的基础,但没写过相关的例子,那我这里提供一个,首先看一下规范 .Net Framework的编码规范: 委托类型的名称都应该以EventHandler结束。 委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。 事件的命名为 委托去掉 EventHandler之后剩余的部分。 继承自EventArgs的类型应该以EventArgs结尾。 然后描述一下流程: 老板监视时间变动(ComputerOffWorkTime方法),当工作时间满50后,通知员工时间到(OnNotifyOffWork方法,并传递OffWorkEventArgs参数),可以下班了,(OnNotifyOffWork方法内部调用事件NotifyOffWork),正式员工收到通知后,则下班,其他员工则清扫一下办公室 然后给出例子: using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; namespace DelegateAndEvent { public class Boss { //表示工作时间 private int virTime; //下班时老板说的话 public String SaidWords { get { return "Boss:时间到,下班了"; } } //委托定义 public delegate void NotifyOffWorkEventHandler(Object sender, OffWorkEventArgs e); //事件 public event NotifyOffWorkEventHandler NotifyOffWork; //事件参数 public class OffWorkEventArgs:EventArgs { public readonly int virTime; public OffWorkEventArgs(int virTime) { this.virTime = virTime; } } //触发事件 protected void OnNotifyOffWork(OffWorkEventArgs e) { if (NotifyOffWork!=null) { NotifyOffWork(this, e); } } //执行操作 public void ComputerOffWorkTime() { for (int i = 1; i <= 50; i++) { virTime = i; if (i>=50) { OffWorkEventArgs e = new OffWorkEventArgs(i); OnNotifyOffWork(e); } } } } //正式员工 public class FormalEmployee { public static void GoHome(Object sender, Boss.OffWorkEventArgs e) { Boss boss = (Boss) sender; Console.WriteLine(boss.SaidWords); Console.WriteLine(e.virTime); Console.WriteLine("FormalEmployee:准备回家"); } } //其他员工 public class OtherEmployee { public static void CleanOffice(Object sender, Boss.OffWorkEventArgs e) { Boss boss = (Boss)sender; Console.WriteLine(boss.SaidWords); Console.WriteLine(e.virTime); Console.WriteLine("OtherEmployee:准备清扫办公室"); } } public class Program { static void Main(string[] args) { Boss boss=new Boss(); //注册事件 boss.NotifyOffWork += FormalEmployee.GoHome; boss.NotifyOffWork += OtherEmployee.CleanOffice; //老板开始计时 boss.ComputerOffWorkTime(); } } }

2013-06-25 · 1 min · bystander

DMP版本修改工具(C#)

最近在使用oracle导入一个dmp文件的时候,由于不知道dmp文件是如何导出的,是使用exp还是expdp导出的,所以纠结了比较长的时间,最后想到是否可以查看dmp文件的一些辅助信息呢,于是有了这个工具。 在使用dmp导入的时候报如下错误 IMP-00010: 不是有效的导出文件,标题验证失败 IMP-00000: 未成功终止导入 据说有两个可能,1个是文件本身损坏,另一个是版本问题,多出现在高版本导出的数据向低版本导入。解决方法就是修改一下dmp文件就行了。dmp文件头部大概9个字节处标识了版本号用来头部验证。对于非常大的dmp我们不能直接用文本编辑器打开,因此找找资料,写个工具。本机一个12GB的文件已测试。 工具使用很简单,选择文件,识别出来版本,按格式改成导入端oracle的版本值,然后即可正常导入11G-10G测试成功。 下载地址:DMP版本修改工具

2013-06-11 · 1 min · bystander

[译]反射(Reflection)和动态(dynamic)

反射 当我们需要检查,调用一个程序集的内容的时候,用反射,比如,当VS给智能提示的时候,就应用了反射。 简单用法实例: var myAssembly = Assembly.LoadFile(@"C:\ClassLibrary1.dll"); var myType = myAssembly.GetType("ClassLibrary1.Class1"); dynamic objMyClass = Activator.CreateInstance(myType); // 获取类的类型信息 Type parameterType = objMyClass.GetType(); // 浏览方法 foreach (MemberInfo objMemberInfo in parameterType.GetMembers()) {Console.WriteLine(objMemberInfo.Name);} // 浏览属性. foreach (PropertyInfo objPropertyInfo in parameterType.GetProperties()) {Console.WriteLine(objPropertyInfo.Name);} //开始调用 parameterType.InvokeMember(“Display”,BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod | BindingFlags.Instance,null, objMyClass, null); 实际一点的用处呢: 1.当你也要开发一个类似VS的编辑器的时候,要提供智能提示就需要反射 2.当创建单元测试框架的时候,为了测试需要动态调用方法和属性的时候 3.有时候我们想把类型的属性,方法等全部导出的时候 动态dynamic 编程语言分为强/弱类型,dynamic是弱类型,此关键字会让编译器不做编译时的类型检查,只做运行时的检查。 简单用法示例: dynamic x = "c#"; x++; 所以上面这行代码可以编译通过,但会产生运行时一场。 实际用处: 最多的就是通过互操作来操作Office组件的时候了 没有dynamic的时候 / Before the introduction of dynamic. Application excelApplication = new Application(); ((Excel.Range)excelApp.Cells[1, 1]).Value2 = "Name"; Excel.Range range2008 = (Excel.Range)excelApp.Cells[1, 1]; 有了dynamic之后世界就不一样了 dynamic excelApp = new Application(); excelApp.Cells[1, 1].Value = "Name"; Excel.Range range2010 = excelApp.Cells[1, 1]; 两者的区别和联系呢 1.当我们想要在运行时操作一个对象的时候,就会用到这两个 2.反射可以用来检测对象的元数据,也能在运行时调用对象的方法和属性 3.dynamic是.net 4.0新出的关键字,知道方法被调用的时候,编译器才会晓得这个方法到底有还是没有。 4.dynamic内部是使用反射来实现的,它缓存了方法调用来提高性能 5.反射可以调用公有和私有成员,而dynamic智能调用用公有成员 6.dynamic是实例相关的,无法访问静态成员,这种情况下使用反射吧。 **Reflection** **Dynamic** **Inspect (meta-data) ** Yes No **Invoke public members** Yes Yes **Invoke private members** Yes No **Caching** No Yes **Static class ** Yes No 再来一张图... [![](/images/d0e1ec824f1199a847d9a16237673a4a299e0dce.jpg)](http://leaverimage.b0.upaiyun.com/36512_o.jpg) 译自:[http://www.codeproject.com/Articles/593881/What-is-the-difference-between?utm_source=feedly](http://www.codeproject.com/Articles/593881/What-is-the-difference-between?utm_source=feedly)

2013-05-27 · 1 min · bystander

武汉大学论文参考文献格式生成工具(C#)

每次写论文报告什么的,最头疼的就是参考文献的,本来打算写一个论文格式生成工具的,不过,一想起代码量,就有点吓人,所以分而治之,先写参考文献生成工具. 本工具生成的文献格式符合武汉大学本科生论文的格式要求,因此,放心使用,填写内容都是必填,页码什么的要是不知道就随便填一个..你懂的..有问题请留言反馈。 程序提供8种参考文献类型,第9种电子文献,没有实现,因为感觉在论文中参考文献要是网址的话很难看.而且用的不多..其实主要还是懒..每种文献类型需要填写的信息都不一样,8种…8种… 使用方法: 1.在界面右侧选择参考文献类型,然后填写。添加,左侧将会出现 2.如果填写错误,双击左侧条目,即可删除 3.完成后导出,即可在本目录生成docx文档 下载地址:武汉大学论文参考文献格式生成工具

2013-05-24 · 1 min · bystander

倒水问题求解(C++)

明天要去参加微软面试,不求顺利,但求体验。 这个题目答题的意思是: 给你一个容量为A升的桶和一个容量为B升的桶,水不限使用,要求精确得到Q升水.请说明步骤 当数字比较小的时候,我们可以通过大脑穷举来得到结果,但这里有两个问题,当数字很大的时候怎么解?题目给定的数据是否有解? 首先判断是否有解? 题目可以理解为,x为用A的次数,y为用B的次数,Q为目标值 Q = A * x + B * y Q =目标值. Q必须是 Gcd(A,B)(也就是A,B的最大公约数)的倍数,否则无解,如果 Gcd(A,B) == 1, 任何Q都是可解的 最简单的方法就是把A的水不断的向B中倒(B向A中倒也行),知道得到最终结果,如果桶满了,就清空该桶.举个例子 A = 3, B = 4 并且 Q = 2 重复得从 A->B A B 0 0 4 0 1 3 1 0 0 1 4 1 2 3 <-A桶中得到2了 试试从 B->A A B 0 0 0 3 3 0 3 3 4 2 <- B中也得到了2 但是注意,从 B->A 比从 A->B快哦 然后我贴出代码 #include "stdafx.h" #include <iostream> #include <vector> #include<string> using namespace std; //热门智力题 - 打水问题 //基本思想:用A桶容量的倍数对B桶的容量进行取余。 //指导方针:不断用A桶装水倒入B桶,B桶满了立即清空 //每次判断下二个桶中水的容量是否等于指定容量。 const string OPERATOR_NAME[7] = { "装满A桶", "装满B桶", "将A桶清空", "将B桶清空", "A桶中水倒入B桶", "B桶中水倒入A桶", "成功得到结果" }; int max(int a,int b) { return a>b?a:b; } int gcd(int m,int n) { int temp,p,r; //n存放最小数,m存放最大数 if(n>m){ temp = n; n = m; m = temp; } p=n*m;//先取得两个数的积 while(n!=0){ r=m%n; m=n; n=r; } return m; } int _tmain(int argc, _TCHAR* argv[]) { int a_capacity, b_capacity, goal_capacity; vector<string> record; //记录操作过程 int a_water, b_water; cout<<"请输入A桶容量,B桶容量,目标容量Q:"; cin>>a_capacity>>b_capacity>>goal_capacity; a_water = b_water = 0; //A桶,B桶中有多少升水 //判断是否一定可解 if (a_capacity<=0 || b_capacity<=0 || goal_capacity<=0) { cout<<"请保证所以容量大于0"<<endl; return -1; } if (goal_capacity>max(a_capacity,b_capacity)) { cout<<"要量出的容量应该小于其中桶容量"<<endl; return -2; } //如果可解则解之 if(goal_capacity%gcd(a_capacity,b_capacity)==0) { //存放临时的字符串构造 char szTemp[30]; while (true) { if (a_water == 0)//A桶没水,就装满水 { a_water = a_capacity; sprintf(szTemp, " A:%d B:%d", a_water, b_water); record.push_back(OPERATOR_NAME[0] + szTemp);//先填满 A桶 } else { //如果A桶的水比(B桶容量-B桶的水)要多,也就是多于没装满的B桶空出来的部分,A桶会剩下 if (a_water > b_capacity - b_water) { //A桶向B桶倒水直到B桶满,此时A桶的水==A桶的水+B桶的水-B桶容量 a_water = a_water + b_water- b_capacity; b_water = b_capacity; //B桶的水装满了 sprintf(szTemp, " A:%d B:%d", a_water, b_water); record.push_back(OPERATOR_NAME[4] + szTemp);//A->B if (a_water == goal_capacity) break; b_water = 0; //将B桶清空 sprintf(szTemp, " A:%d B:%d", a_water, b_water); record.push_back(OPERATOR_NAME[3] + szTemp); } else { //A桶小于装满B桶需要的水,此时B桶的水==A桶的水+B桶的水 b_water += a_water; a_water = 0; sprintf(szTemp, " A:%d B:%d", a_water, b_water); record.push_back(OPERATOR_NAME[4] + szTemp);//A->B if (b_water == goal_capacity) break; } } } record.push_back(OPERATOR_NAME[6]); //break出来说明成功了 cout<<"\n---------------------------------------------------"<<endl; cout<<"以下下是一种方案"<<endl; vector<string>::iterator pos; for (pos = record.begin(); pos != record.end(); pos++) cout<<*pos<<endl; cout<<"---------------------------------------------------"<<endl; } else { cout<<"此情况下无解"<<endl; } return 0; } 运行结果如下: ...

2013-05-15 · 2 min · bystander

[已失效]Csdn免积分下载器

作者:bystander 转载请注明来源:http://leaver.me 原理很简单,目前好像还没有大规模传开,我就不透露了,大家低调使用.为了方便,我写了个客户端,下载地址在文章末尾 使用方法直接把你想下载的地址复制过去,点击下载就会调用ie来下载了. 文章太短了,发两个可乐的吧: 第一个是: "网上发言,请不要随便自称笔者,毕竟有没有在用笔在写一目了然。这个词汇已经要汇入历史长河了,虽然曾经的那么疯狂存在过,但至少在互联网上该消失了。" "那以后自称什么?" "键人。" ---------------------------------------------------------------------------------------------------------- 第二个: ---光棍君:五一快到了,你还是一个人吗? ---你MB,难道我会变成狗吗? ---------------------------------------------------------------------------------------------------------- 第一个冷笑话,第二个是热笑话,冷暖自知。一个成语瞬间提升了整篇文章的境界。 下载地址:[Csdn下载器](http://pan.baidu.com/share/link?shareid=468747&uk=1493685990)

2013-05-01 · 1 min · bystander

一道笔试指针题目详解

看到本题是在搜狗某年的笔试题上,看也没人给出非常详细的讲解,直接给出了答案,我来尝试写一写, 貌似本题来源自<**The C Puzzle Book> ,**搜狗也只是换了一下字符串,直接看题吧 #include <stdio.h> char *c[]={"ENTNG", "NST","AMAZI","FIRBE"}; char** cp[]={c+3, c+2, c+1, c}; char ***cpp= cp; int main() { printf("%s",**++cpp); printf("%s ",*--*++cpp+3); printf("%s",*cpp[-2]+3); printf("%s",cpp[-1][-1]+1); } <span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;">请写出程序的执行结果....</span> 首先从左到右看: char *c[]= { "ENTNG", "NST", "AMAZI", "FIRBE" }; *c[] 是一个字符,因此,c[]是指向该字符,c就是一个数组(数组的内容为指向字符的指针),c已经被初始化了. char** cp[]={c+3, c+2, c+1, c}; 再看第二行,**cp[]是一个字符,*cp[]就是一个指针,指向该字符,cp[]就是一个指针,指向该指针,而cp就成为了指针数组,内容是指向字符的指针的指针。并且通过c的元素进行了初始化 char ***cpp= cp; 第三行,***cpp是一个字符,**cpp指向该字符,*cpp指向该指针,cpp就指向该字符的指针的指针. 然后我画一张图表示初始的情况看看 然后对于下面的输出语句,通过操作符优先级使用括号来区分一下: *(*(++cpp)); 这个嘛,就是把cpp后移(注意cpp已经改变了)然后就指向了cp[1],然后两次取其值即可得到AMAZI 推导过程如下: ++cpp -> cp[1] // cp[1] -> c+2 ++cpp = &cp[1] // &(c+2) *++cpp = *(&c+2) // c[2] **++cpp = *&c[2] 然后看第二个 (*(--(*(++cpp))))+3; 加括号后如上,cpp再加一,就指向了cp[2],取一次值(也就是*号)就变成了c[1],然后--c[1]就指向了c[0],取值就成了c[0]的地址,然后地址+3,就是NG了 (*(cpp[-2]))+3; 上面,cpp指向cp[2]了,然后呢,cpp[-2] 相当于*(cpp-2),间接引用cp[2],这样cpp[-2]就指向了cp[0]了,然后,就是FIRBE了,加3就是BE了 最后 (cpp[-1][-1])+1; cpp还是之前的cp[2],cpp[-1][-1]相当于*(*(cpp-1)-1),先减1指向了cp[1],取一次值就是c[2]了,然后c[2]-1就成为c[1]了,然后+1之后就是ST了. 所以,最后输出就是 AMAZINGBEST 错误之处还望指正.

2013-04-17 · 1 min · bystander

模板优先级队列及堆排序(C++实现)

模板优先级队列,数组实现,再熟悉一下常用算法,同时简单的堆排序应用 写了一个是队列自增长,另一个为了演示我还添加了一个叫做FillPq的方法,这个方法可以使用一个数组直接填充到优先级队列里,此时,优先级队列并不优先,然后进行下滤调整,之后建堆完成,输出即可 #include "stdafx.h" template< class T> class PriorityQueue { private: T *pq; int N; int capacity; public: PriorityQueue(void); ~PriorityQueue(void); void Insert(T x); T DelTop(); void Swim(int k); void Sink(int k); bool Less(int i,int j); void Swap(int i,int j); bool Resize(); void FillPq(T arr[],int size); }; template< class T> void PriorityQueue<T>::FillPq( T arr[],int size ) { N=size; capacity=2*size; for (int i=0;i<size;i++) { pq[i+1]=arr[i]; } } template< class T> PriorityQueue<T>::PriorityQueue(void) { pq=new T[10]; N=0; capacity=10; } template< class T> void PriorityQueue<T>::Insert( T x ) { if (N==capacity) { Resize(); } pq[++N]=x; Swim(N); } template< class T> T PriorityQueue<T>::DelTop() { T max=pq[1]; Swap(1,N--); Sink(1); pq[N+1]=NULL; return max; } //下滤 template< class T> void PriorityQueue<T>::Sink( int k ) { while (2*k<=N) { int j=2*k; if (j<N && Less(j,j+1)) { j++; } if (!Less(k,j)) { break; } Swap(k,j); k=j; } } //上浮 template< class T> void PriorityQueue<T>::Swim( int k ) { while (k>1 && Less(k/2,k)) { Swap(k,k/2); } } template< class T> void PriorityQueue<T>::Swap( int i,int j ) { T temp=pq[i]; pq[i]=pq[j]; pq[j]=temp; } template< class T> bool PriorityQueue<T>::Less( int i,int j ) { return pq[i]<pq[j]; } template< class T> bool PriorityQueue<T>::Resize() { T *newPq=new T[capacity*2]; capacity=capacity*2; for (int i=1;i<=N;i++) { newPq[i]=pq[i]; } pq=newPq; return true; } template< class T> PriorityQueue<T>::~PriorityQueue(void) { } 然后是堆排序 ...

2013-04-16 · 2 min · bystander

模板栈以及中缀表达式求值(C++实现)

栈直接用链表实现,这个比较简单,不多说,不过C++写程序,IDE的错误检测不是很给力。 至于给定一个中缀表达式,如何不转换成后缀表达式,直接求值,方法就是使用两个栈,一个操作符栈,一个操作数栈,然后从左到右扫描表达式,我这里中缀表达式计算实现的很简单,不完整,大家可以扩展。栈的实现是我想写的,思路如下: 1.如何是操作数,压入操作数栈 2.如果是操作符,压入操作符栈 3.如果是左括号,直接忽略 4.如果是有括号,弹出操作符栈栈顶元素,然后弹出操作数栈两个元素,进行操作以后结果压入操作数栈 看个图就好了 最后给出栈顶实现代码 #include "stdafx.h" #pragma region Node定义 template <class T> class Node { template<class T> friend class Stack; private: T m_data; Node *pNextNode; public: Node(); Node(T d); }; template <class T> Node<T>::Node() { m_data=default(T); pNextNode=NULL; } template <class T> Node<T>::Node(T d) { m_data=d; pNextNode=NULL; } #pragma endregion #pragma region Stack定义 template <class T> class Stack { private: Node<T> *m_pTopNode; int m_nNodeCount; public: Stack(); ~Stack(); bool IsEmpty(); bool Push(T e); T Pop(); int Size(); }; template <class T> Stack<T>::Stack() : m_pTopNode(NULL),m_nNodeCount(0) { } template <class T> Stack<T>::~Stack() { while (!IsEmpty()) { Node<T> *pTempNode = m_pTopNode; m_pTopNode = m_pTopNode->pNextNode; delete (pTempNode); pTempNode = NULL; } m_nNodeCount = 0; m_pTopNode = NULL; } template <class T> bool Stack<T>::IsEmpty() { return (m_pTopNode == NULL); } template <class T> bool Stack<T>::Push(T e ) { Node<T> *pNewNode = new Node<T>(e); if (NULL == pNewNode) { return false; } if(! IsEmpty()) { pNewNode->pNextNode = m_pTopNode; } m_pTopNode = pNewNode; m_nNodeCount ++; return true; } template <class T> T Stack<T>::Pop() { if(IsEmpty()) { return T(-1); } T e; e = m_pTopNode->m_data; Node<T> *pNode = m_pTopNode; m_pTopNode = m_pTopNode->pNextNode; delete (pNode); m_nNodeCount--; return e; } template <class T> int Stack<T>::Size() { return m_nNodeCount; } #pragma endregion 然后是main函数代码 ...

2013-04-11 · 2 min · bystander

并查集(C++实现)

并查集这个很有意思,并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。昨天看书看到了,然后用C++简单实现了下。在Dijkstra算法中,用来判断两个顶点是否在同一个集合里。 里面定义了两个类,都是并查集,一个是QuickFind,查找很快,一个是QuickUnion,合并较快。写了一些注释,有一些优化的提示.看代码吧,有什么问题指出来吧。 QuickFind的实现 #include "QuickFind.h" QuickFind::QuickFind(int N) { size=N; id=new int[N]; for(int i=0;i<N;i++) { id[i]=i; } } bool QuickFind::Find(int p,int q) { return id[p]==id[q]; } void QuickFind::Unite(int p,int q) { int pid=id[p]; for(int i=0;i<size;i++) if(id[i]==pid) id[i]=id[q]; } QuickFind::~QuickFind(void) { delete []id; } QuickUnion的实现 #include "QuickUnion.h" QuickUnion::QuickUnion(int N) { size=N; id=new int[N]; for(int i=0;i<N;i++) { id[i]=i; } } int QuickUnion::root(int i) { while (i!=id[i]) { //id[i]=id[id[i]]; 若添加这句话则为压缩路径 i=id[i]; } return i; } bool QuickUnion::Find(int p,int q) { return root(p)==root(q); } void QuickUnion::Unite(int p,int q) { //将p的根挂在q的根上, //这样会导此数变高,若需要优化,需要设置另一个 //数组sz[],sz[i]表示所以根为i的节点的数目,然后将 //小树靠在大树上 /* int i=root(p); int j=root(q); if(sz[i]<sz[j]) { id[i]=j;sz[j]+=sz[i]; } else { id[j]=i;sz[i]+=sz[j]; }*/ int rootp=root(p); int rootq=root(q); id[rootp]=rootq; } QuickUnion::~QuickUnion(void) { delete []id; } 参考文档(英文):UnionFind.pdf 工程代码下载:并查集Demo

2013-04-11 · 1 min · bystander