20170717-20170723C#工作学习周总结

来源:互联网 发布:淘宝退货不退钱怎么办 编辑:程序博客网 时间:2024/06/03 19:08

2017.07.17-2017.07.23

一、委托

委托实例化后可以与方法关联,在调用委托的同时会调用与之关联的方法。这使得我们可以把方法当作参数传递给其他方法。从运行方式来看,委托与C语言中的函数指针类似。

Q & A

Q:

C#中,直接用类名声明一个变量和new一个对象有什么区别?

A:

存储方式不同,new在堆栈里面,直接声明的是局部变量了,运行的时候默认值为null;

new的用完要delete,直接声明函数执行完自动释放了;

C#的new同时负责内存的分配以及把实例初始化成有效状态;

Q:

多线程怎么得到返回值

A:

线程就是用来处理并发的事情的,而你所说的线程的返回值,实际上,你的思想仍然停留在函数调用的模式上(把线程看成了函数)
线程的返回值问题,最理想的办法就是线程来通知调度线程,这个调度线程可以是主线程,也可以是一个专门的调度线程,每当任务线程完成了自己的工作,就通知调度线程来取结果,这样才能够发挥出多线程的优势,而不是在那里傻等。
如果你把主线程当做调度线程,而你的主线程存在消息循环,那么,利用消息就是一个不错的通知方式。
任务线程完成了工作之后,向主线程发消息,消息中可以把任务线程本身(线程类)发给主线程,然后在主线程中取出这个线程类,然后得到任务线程的处理结果。
而最为主线程,只需要添加一个消息响应函数就可以了。

Q:

string[] a = new string[] { “1”, “2”, “3” };

我想给a追加一个 “4” 元素 怎么写呢?因为别人的参数方法能接受 string[] 这个类型 因此不能用Array 求解决!

A:

string[] a = new string[] { “1”, “2”, “3” };
List b = a.ToList();
b.Add(“4”);
a = b.ToArray();

一般习惯先转List,处理完了再丢给数组。

二、一个简单的跨线程更新UI(进度条)的程序

//TestClass类,可以用来,线程函数在其中实现using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace _20170720{    class TestClass    {        public delegate void testDelegate(long i);        public testDelegate mainThread;        public void TestFunction()        {            long i = 0;            while (true)            {                i++;                if (mainThread !=null)                {                    mainThread(i);                }                Thread.Sleep(100);            }        }    }}
//Program类,用来实现窗体及更新UIusing System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading;using System.Windows.Forms;namespace _20170720{    public partial class Form1 : Form    {        public Form1()        {            InitializeComponent();        }        private void button1_Click(object sender, EventArgs e)        {            //创建TestClass类的对象            TestClass testclass = new TestClass();            testclass.mainThread = new TestClass.testDelegate(refreshLabMessage1);            testclass.mainThread += new TestClass.testDelegate(refreshLabMessage2);            testclass.mainThread = new TestClass.testDelegate(refreshProgressBar);            Thread testClassThread = new Thread(new ThreadStart(testclass.TestFunction));            testClassThread.Start();        }        private void refreshLabMessage1(long i)        {            if (this.label1.InvokeRequired)            {                if(label1.Disposing||label1.IsDisposed)                {                    return;                }                TestClass testclass = new TestClass();                testclass.mainThread = new TestClass.testDelegate(refreshLabMessage1);                this.Invoke(testclass.mainThread, new object[] { i });            }            else            {                label1.Text = i.ToString();            }        }        private void refreshLabMessage2(long i)        {            if (this.label1.InvokeRequired)            {                if (label1.Disposing || label1.IsDisposed)                {                    return;                }                TestClass testclass = new TestClass();                testclass.mainThread = new TestClass.testDelegate(refreshLabMessage2);                this.Invoke(testclass.mainThread, new object[] { i });            }            else            {                label1.Text = i.ToString();            }        }        private void refreshProgressBar(long i)        {            if (progressBar1.InvokeRequired)            {                if(progressBar1.Disposing||progressBar1.IsDisposed)                {                    return;                }                TestClass testclass = new TestClass();                testclass.mainThread = new TestClass.testDelegate(refreshProgressBar);                this.Invoke(testclass.mainThread, new object[] { i });            }            else            {                progressBar1.Value = (int)i;            }        }    }}

三、一个对象数组排序的实例

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace dele{    class Program    {        static void Main(string[] args)        {            StudentInformationClass[] studentsInfo;            Student[] students = new Student[]{                new Student(){Age = 10,Name="张三",Score=70},                new Student(){Age = 12,Name="李四",Score=97},                new Student(){Age = 11,Name="王五",Score=80},                new Student(){Age = 9,Name="赵六",Score=66},                new Student(){Age = 12,Name="司马",Score=90},            };            Console.WriteLine("--------------默认排序输出--------");            Array.Sort(students);            Array.ForEach<Student>(students, (s) => Console.WriteLine(string.Format("{0}{1,2}岁了,他的分数是{2,3}", s.Name, s.Age, s.Score)));            Console.Read();        }    }    public class Student:IComparable    {        public int Age { get; set; }        public string Name { get; set; }        public int Score { get; set; }        /// <summary>        /// 实现IComparable接口,用Age做比较        /// </summary>        /// <param name="obj">比较对象</param>        /// <returns>比较结果</returns>        public int CompareTo(object obj)        {            if (obj is Student)            {                return Age.CompareTo(((Student)obj).Age);            }            return 1;        }    }}

关于构造函数

类当中会有一个默认的无参数的构造函数,当写了一个新的构造函数之后不管是有参的还是无参的,默认的构造函数都会被干掉,这个时候要想用类原来默认的构造函数,就需要加:this()

WIMP

指:windows,icon,menus&pointer,是图形界面电脑所采用的界面典范。

  • A window runs a self-contained program, isolated from other programs that (if in a multi-program operating system) run at the same time in other windows.
  • An icon acts as a shortcut to an action the computer performs (e.g., execute a program or task).
  • A menu is a text or icon-based selection system that selects and executes programs or tasks.
  • The pointer is an onscreen symbol that represents movement of a physical device that the user controls to select icons, data elements, etc.

window和control为同一个父类。

事件和消息机制的理解

一个/条消息可以理解为是一个数据结构,包含以下几个基本部分:

  1. 消息源 :就是消息的来源,发出这个消息的对象
  2. 消息名 :就是消息的唯一标示
  3. 消息数据:消息发出后附带的数据,有可能数据是空

消息从种类上又可以分为2种:

  1. 系统消息 :由操作系统或deviceone系统发送出来的消息,消息的名称是固定的。
  2. 自定义消息:由开发者自己定义,自己发送出来的消息,消息的名字是随意的,可以任意定义。

发布/订阅模式是最常用的设计模式之一,是消息机制的核心,其特点就是降低耦合度,让二个独立的对象不互相依赖。

img

  1. 消费者和出版社互相不认识,消费者不需要了解他想要的杂志是具体哪家出版社出的;出版社也不需要了解具体是哪个人定了他们出版社发行的书。
  2. 消费者和出版社必须都认识邮局。
  3. 消费者需要告诉邮局消费者的名字地址以及想要订阅的杂志名字
  4. 可以多个消费者订阅同一本杂志
  5. 邮局拿到杂志后,会一一通知消费者,通知的时候同时把杂志送到消费者手里。

img

和上面的实际例子描述一一对应:

  1. 系统/开发者和函数对象互相不依赖,系统/开发者只管触发一个消息,并不关心谁去接受
  2. 系统/开发者和函数对象必须能获取到消息源对象
  3. 函数对象订阅消息的时候需要标示消息的名称和函数对象的引用
  4. 可以多个函数对象订阅同一个消息源同一名字的消息
  5. 消息源触发消息会一一通知所有订阅者,并把data数据传递到回调函数对象

事件:只能由用户通过外设的输入产生。

消息:(产生消息的来源有三个) (1) 由操作系统产生。 (2) 由用户触发的事件转换而来。 (3) 由另一个消息产生。

在C#中定义一个事件,首先要创造一个委托,用委托来定义一个你想使用的事件的标签,然后才能使用event关键字,在这个委托的基础上定义一个事件,然后把触发事件的源和事件处理机制关联起来。

继承

继承、封装和多态是面向对象编程的重要特性。其成员被继承的类叫基类也称父类,继承其成员的类叫派生类

也称子类。

派生类隐式获得基类的除构造函数和析构函数以外的所有成员。

派生类只能有一个直接基类,所以C#并不支持多重继承,但一个基类可以有多个直接派生类。
继承是可以传递的。

即:

如果 ClassB 派生出 ClassC,ClassA 派生出 ClassB,则 ClassC 会继承 ClassB 和 ClassA 中声明的成员。

析构函数与构造函数的区别

析构函数用于释放被占用的系统资源。

  1. 构造函数和析构函数是在类中说明的两种特殊的成员函数。
  2. 构造函数是在创建对象时,使用给定的值将对象初始化。
  3. 析构函数用于释放一个对象。在对象删除前,使用析构函数做一些清理工作,它与构造函数的功能正好相反。

自定义控件

在编程的过程中,当现有C#的控件满足不了我们的业务需求时,这就需要自己开发组件来达到我们的要求,即我们通常所说的自定义组件,在C#中,自定义组件分为三种:

  1. 复合控件(Composite Controls):将现有的各种控件组合起来,形成一个新的控件,来满足用户的需求。
  2. 扩展控件(Extended Controls):就是在现有的控件基础上,派生出一个新的控件,增加新的功能,或者修改原有功能,来满足用户需求。
  3. 自定义控件(Custom Controls):就是直接从System.Windows.Forms.Control类派生,也就是说完全由自己来设计、实现一个全新的控件。

​ 第一种方法比较简单,直接拼凑即可,但是功能上 比不上第二、三种;第二种是比较常见的方法,对现有控件的属性、方法等进行扩展,功能上基本能满足一般的需求。第三种实现的功能更强大,也更灵活,从Control类继承,控件的属性、方法、事件等全部由自己编码实现,这要求编写者拥有一定的C#编程经验和GDI/GDI+技能。

比如,可以用复合控件(用户控件)来实现文件的打开并显示路径。即将textbox和button结合起来,将接口留给属性,用get/set方法实现。

关于内核

内核对象即CPU特权指令,内核即指执行特权指令的那部分代码。与Handle交互的时候要用到内核对象,句柄会泄露,打开就要负责关闭。

原创粉丝点击