主頁 > 軟體設計 > C#復習筆記

C#復習筆記

2021-12-27 07:51:47 軟體設計

第一章 C#概述:

1、CLR的概念和功能

CLR是一個可以由多編程語言使用的運行時,
CLR的核心功能:記憶體管理,程式集加載,安全性,例外處理,執行緒同步等等,可以被很多屬于微軟系列的開發語言使用,

2、 C#的優勢和特點

特點:跨平臺、跨語言、跨標準
優勢:適用于windows平臺

3、 C#開發.NET應用程式的步驟

C#開發,NET應用程式的步驟

4、 C#源程式檔案、vs解決方案檔案、Web專案檔案、C#專案檔案的后綴名

擴展名

5、 第一個簡單的C#應用程式

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

第二章 C#編程基礎

1、System.Array的屬性與方法

System.Array是所有陣列型別的抽象基型別,所有的陣列型別均由它派生,任何陣列都可以使用System.Array具有的屬性及方法
System.Array

2、一維陣列的宣告、創建、初始化

//宣告
int a[];
//創建
a = new int[4];
int a = new int[4];
const int i = 4; int a = new int[i];
//初始化
for (int i = 0; i < fs.Length; i++)
	fs[i]=i;
type[] arrayName = new type[size]{val1,val2,,valn};
type[] arrayName = new type[] { val1, val2,, valn };
float[] fs = { 21.34f, 37.58f, 776.46f, 834.23f };
float[] fs;
fs = new float[] { 21.34f, 37.58f, 776.46f, 834.23f };

3、規則與鋸齒狀二維陣列的宣告、創建、初始化

//宣告
陣列元素型別[,] 陣列名; Point[,] ps;
陣列元素型別[][] 陣列名; Point[][] ps;
//創建
陣列名 = new 陣列元素型別[一維元素個數][二維元素個數];
ps = new Point[4][]; //鋸齒狀二維陣列
陣列名 = new 陣列元素型別[一維元素個數, 二維元素個數];
ps = new Point[4, 5]; //規則二維陣列
//初始化
Point[][] ps = new Point[3][]; //鋸齒狀二維陣列的初始化
for (int i = 0; i < ps.GetLength(0); i++)
{
	ps[i] = new Point[5];
	for (int j = 0; j < ps[i].Length; j++)
		ps[i][j] = new Point(i + 1, j + 1);
}
Point[,] ps = new Point[3, 4]; //規則二維陣列的初始化
for (int i = 0; i < ps.GetLength(0); i++)
	for (int j = 0; j < ps.GetLength(1); j++)
		ps[i][j] = new Point(i + 1, j + 1);
		
int[,] a = new int[2, 3] { { 0, 1, 2 }, { 3, 4, 5 } };

int[,] a = new int[,] { { 0, 1, 2 }, { 3, 4, 5 } };

int[,] a = { { 0, 1, 2 }, { 3, 4, 5 } };

int[,] a; a = new int[2, 3] { { 0, 1, 2 }, { 3, 4, 5 } };

char[][] st1 = new char[3][];
st1[0] = new char[] {‘S’,’e’,’p’,’t’,’e’,’m’,’b’,’e’,’r’};
st1[1] = new char[] {‘O’,’c’,’t’,’o’,’b’,’e’,’r’};
st1[2] = new char[] { ‘N’,’o’,’v’,’e’,’m’,’b’,’e’,’r’};

4、陣列的Length屬性

一維陣列:陣列名.Length 是陣列元素的個數
二維陣列:
陣列名.Length 是規則二維陣列含有的總元素的個數
int[,] c = new int[3, 4]; //c.Length為12
陣列名.Length 是鋸齒狀二維陣列含有的一維陣列的個數
int[][] c = new int[3][]; //c.Length為3

5、foreach陳述句

//foreach (型別 識別符號 in 集合運算式)
	//陳述句;
int[] ints = { 1, 2, 3 };
foreach (int temp in ints)
	Console.WriteLine(temp);

6、動態陣列ArrayList

  • 需引入System.Collections命名空間
  • Array與ArrayList的區別
  • Array的容量固定,而ArrayList可以動態擴充
  • ArrayList提供添加、插入或移除某一范圍元素的方法,在Array中,只能一次獲取或設定一個元素的值
  • Array可以是多維的,而ArrayList是一維的
ArrayList arr = new ArrayList();
string str1;
str1 = Console.ReadLine();
arr.Add(str1);

第三章 面向物件編程基礎

1、屬性及屬性的修飾符

  • 屬性的定義
//定義屬性結構
public int MyIntProp{
	get{
		//get code
	}
    set{
            //set cod
	}
}
  1. 定義屬性需要名字和型別,
  2. 屬性包含兩個塊:get塊和set塊,
  3. 訪問屬性和訪問欄位一樣,當取得屬性的值得時候,就會呼叫屬性中的get塊,因此get塊需要回傳值,其回傳值型別就是屬性的型別;當我們去給屬性設定值得時候,就會呼叫屬性中的set塊,以此可以在set塊中通過value訪問到我們所設定的值,
  4. 屬性的種類和修飾符
//只讀
private string name;
public string Name{
    get{
            return name;
	}
}
//只寫
private string name;
public string Name{
    set{
            name = value;
	}
}
//可讀寫
private string name;
public string Name{
    get{
            return name;
	}
	set{
            name = value;
	}
}
//static屬性:只能訪問靜態資料
public static int LoginCount {
	get{
		return m_LoginCount;//m_LoginCount為靜態資料
	}
}
//如果在get或set塊錢加上private,表示這個塊只能在類內進行呼叫
public float X{
    private set { x = value;}  
    get { return x;}
}
public float X{
    set { x = value;}  
    private  get { return x;} 
}
//自動實作的屬性
public int Age{set;get;}    //編譯器會自動提供欄位來存盤age
-->等價于
public int Age{
    set{ age = value;}
    get{ return age;}

2、屬性與欄位的區別和聯系

  • 均可以訪問物件中包含的資料
  • 屬性不能直接訪問資料
  • 屬性可以限制數值的取值范圍
  • 屬性可設定為僅讀、僅寫、可讀寫
  • 屬性可以象方法一樣使用virtual、abstract、override、new、static等修飾符,而這些修飾符不能用于欄位

3、抽象屬性

abstract class A {
    protected int x;

    public abstract int X {
        get;
        set;
    }
}
class B : A{
    public B(int a) {
        x = a;
    }
    public override int X {
        get {
            Console.WriteLine("in class B property X get block");
            return x;
        }
        set {
            Console.WriteLine("in class B property X set block");
            x = value;
        }
    }
}

4、類的修飾符

類修飾符
- 其他修飾符

  • abstract 抽象類,含有抽象成員,因此不能被實體化,只能用作基類
  • sealed 密封類,不能從該類派生出其他類

5、方法的修飾符

方法修飾符
- 其他修飾符

  • new
  • static
  • virtual
  • abstract
  • override
  • sealed

6、修飾符的無效組合

無效

7、集合與foreach回圈

- 集合

  • .NET提供實作集合的介面,包括IEnumerable,ICollection,IList,IDictionary, IDictionaryEnumerator, IComparer等,只需繼承實作集合介面
  • 也可以直接使用.NET已經定義的集合類,包括Array, ArrayList, Queue, Stack, BitArray,Hashtable
using System;
using System.Collections;

namespace CustomCollection
{
    //定義集合中的元素所屬的類
    class MyClass
    {
        public string Name;
        public int Age;
        public MyClass(string name, int age)
        {
            this.Name = name;
            this.Age = age;
        }
    }
    public class Iterator : IEnumerator, IEnumerable
    {
        private MyClass[] ClassArray;
        int Cnt;
        public Iterator()
        {
            ClassArray = new MyClass[4];
            ClassArray[0] = new MyClass("Kith", 23);
            ClassArray[1] = new MyClass("Smith", 30);
            ClassArray[2] = new MyClass("Geo", 19);
            ClassArray[3] = new MyClass("Greg", 14);
            Cnt = -1;
        }
        //實作IEnumerator的Reset()方法
        public void Reset()
        {
            Cnt = -1;
        }
        //實作IEnumerator的MoveNext()方法
        public bool MoveNext()
        {
            return (++Cnt < ClassArray.Length);
        }
        //實作IEnumerator的Current屬性
        public object Current
        {
            get
            {
                return ClassArray[Cnt];
            }
        }
        //實作IEnumerable的GetEnumerator()方法
        public IEnumerator GetEnumerator()
        {
            return (IEnumerator)this;
        }
        static void Main()
        {
            Iterator It = new Iterator();
            foreach (MyClass mc in It)
            {
                Console.WriteLine("Name: " + mc.Name);
                Console.WriteLine("Age: {0}", mc.Age);
            }
        }
    }
}

  • foreach回圈隱藏呼叫IEnumerable的GetEnumerator方法得到Iterator,并將集合指向-1的位置
  • foreach回圈反復呼叫MoveNext方法移動集合,使用Current獲取集合當前元素

8、索引器

索引器

class IndexClass //帶索引器的類(下標為整數)
{
    private string[] name = new string[10];
    public string this[int index]
    {
        get { return name[index]; }
        set { name[index] = value; }
    }
}
// 索引器的使用
        IndexClass b = new IndexClass();
        b[0] = "張三";
        b[1] = "李四";
        b[2] = "王五";
        Console.WriteLine("b[0]=" + b[0]);
        Console.WriteLine("b[1]=" + b[1]);
        Console.WriteLine("b[2]=" + b[2]);
class IndexClass //帶索引器的類(下標為字串)
{
    private Hashtable name = new Hashtable();
    public string this[string index]
    {
        get { return name[index].ToString(); }
        set { name.Add(index, value); }
    }
}
// 索引器的使用
        IndexClass b = new IndexClass();
        b["A001"] = "張三";
        b["A002"] = "李四";
        b["A003"] = "王五";
        Console.WriteLine("b[\"A001\"]=" + b["A001"]);
        Console.WriteLine("b[\"A002\"]=" + b["A002"]);
        Console.WriteLine("b[\"A003\"]=" + b["A003"]);
//索引器可多載
public string this[int index] {//A索引器
        get { return name[index].ToString(); }
        set { name.Add(index, value); }
}
public int this[string aName] {//B索引器
        get {
            foreach (DictionaryEntry d in name) {
                if (d.Value.ToString() == aName)
                    return Convert.ToInt32(d.Key);
            }
            return -1;
        }
        set { name.Add(value, aName); }
}

9、索引器與陣列的不同點 索引器與屬性的不同點

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

//多個引數索引器
public int this[string name, int courseID] {
	get {
		foreach (CourseScore cs in arrCourseScore) {
			if (cs.Name == name && cs.CourseID == courseID) {
                    return cs.Score;
			}
		}
		return -1;
	}
	set {
		arrCourseScore.Add(new CourseScore(name, courseID, value));
	}
}

10、委托 委托應用——異步回呼 如何委托 委托與C++函式指標的區別

- 委托的定義
委托是函式的封裝,它代表一類函式,它們都符合一定的簽名:擁有相同的引數串列和回傳值型別,

  • 委托的實體代表一個具體的函式
  • 一旦為委托分配了方法,委托將與該方法具有完全相同的行為
    在這里插入圖片描述
  • 委托的定義使用
public delegate int AddDel(int a, int b);//定義委托,回傳int,引數int,int
class A {
    public static int AddFunc(int x, int y)//該方法符合委托的簽名:回傳int,引數int,int
    { return x + y; }
}
class Program {
    static void Main(string[] args) {
        AddDel ad = new AddDel(A.addFunc);//實體化委托
        Console.WriteLine(ad(2, 3));//執行
    }
}
  • 委托的應用
using System;

delegate bool CompareOp(object a, object b);//委托的定義
class BubbleSorter {
    static public void Sort(object[] sortArray, CompareOp co) {//委托作為引數
        for (int i = 0; i < sortArray.Length; i++) {
            for (int j = 0; j < i; j++) {
                if (co(sortArray[j], sortArray[i])) {
                    object temp = sortArray[i];
                    sortArray[i] = sortArray[j];
                    sortArray[j] = temp;
                }
            }
        }
    }
}
class Employee {
    private string name;
    private decimal salary;
    public Employee(string name, decimal salary) {
        this.name = name;
        this.salary = salary;
    }
    public override string ToString() {
        return string.Format(name + ",{0:C}", salary);
    }
    public static bool Compare(object e1, object e2) {//該方法符合委托簽名,回傳bool,引數object,
        Employee ee1 = (Employee)e1;
        Employee ee2 = (Employee)e2;
        return (ee1.salary > ee2.salary) ? true : false;
    }
}
class Test {
    static void Main(string[] args) {
        Employee[] employees = {new Employee("王平", 2000), new Employee("李明", 1970), 
        						new Employee("孫麗", 1800), new Employee("付新", 1950), 
        						new Employee("林笑", 1900) };
        CompareOp EmployeeCompareOp = new CompareOp(Employee.Compare);
        BubbleSorter.Sort(employees, EmployeeCompareOp);
        for (int i = 0; i < employees.Length; i++)
            Console.WriteLine(employees[i].ToString());
    }
}

11、多播

  • 一次委托可以呼叫多個方法
  • 通過+和-運算子可以實作多播的增加或減少
  • 將多個方法組合到一個委托中,如果方法的回傳值非void,則通過委托呼叫方法僅得到最后一個方法的回傳值,其它的回傳值都將丟失
  • 將多個方法組合到一個委托中,會順序呼叫委托中的每個方法

在這里插入圖片描述

//呼叫實體方法
WorkerClass wr = new WorkerClass();
SomeDelegate d1 = new SomeDelegate(wr.InstanceMethod);
Console.WriteLine("Invoking delegate InstanceMethod, return={0}", d1(5, "aaa"));
//呼叫靜態方法
SomeDelegate d2 = new SomeDelegate(WorkerClass.StaticMethod);
Console.WriteLine("Invoking delegate StaticMethod, return={0}", d2(5, "aaa"));
//多播
SomeDelegate d3 = d1 + d2;
Console.WriteLine("Invoking delegates d1 and d2(multi-cast),return={0} ", d3(5, "aaa"));
//委托中的方法個數
int num_method = d3.GetInvocationList().Length;
Console.WriteLine("Number of methods referenced by delegate d3: {0}", num_method);
//多播d3減去委托d2
d3 = d3 - d2;
Console.WriteLine("Invoking delegates d1 (multi-cast),return={0} ", d3(5, "aaa"));
//委托中的方法個數
num_method = d3.GetInvocationList().Length;
 Console.WriteLine("Number of methods referenced by delegate d3: {0}", num_method);

12、事件

//System.EventArgs是包含事件資料的類的基類
//MyEventArgs類派生于EventArgs,實作自定義事件資料的功能(自己定義的一個類)
class EventSource {	//發布事件的類
    MyEventArgs EvArgs = new MyEventArgs("觸發事件");
    //定義事件委托
    public delegate void EventHandler(object from, MyEventArgs e);
    //定義事件
    public event EventHandler TextOut;
    //激活事件的方法
    public void TriggerEvent() {
        if (TextOut != null)
            TextOut(this, EvArgs);
    }
}
EventSource evsrc = new EventSource();
//CatchEvent的簽名要與定義的委托EventHandler的簽名要相同
//訂閱事件
evsrc.TextOut += new EventSource.EventHandler(CatchEvent);
//觸發事件
evsrc.TriggerEvent();
//取消訂閱事件
evsrc.TextOut -= new EventSource.EventHandler(CatchEvent);
//觸發事件
evsrc.TriggerEvent();

13、一瓶牛奶與一張報紙的故事示例,彼得的故事示例

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
public interface IMilkBox
{
    void PutMilkIn(string s);
}
public interface INewsPaperBox
{
    void PutNewsPaperIn(string s);
}
public class Subscriber : INewsPaperBox, IMilkBox//訂購者類
{
    public string name;

    public Subscriber(string name)
    {
        this.name = name;
    }

    public void PutNewsPaperIn(string s)
    {
        Console.WriteLine("{0} 在報箱里收到送來的 {1}", name, s);
    }

    public void PutMilkIn(string s)
    {
        Console.WriteLine("{0} 在奶箱里收到送來的 {1}", name, s);
    }
}

public class NewsPaperSender
{
    // 介面實作 
    protected ArrayList subscribers = new ArrayList();

    public void SendNewsPaper()
    {
        foreach (INewsPaperBox newsPaperBox in subscribers)
            newsPaperBox.PutNewsPaperIn(" 報紙 ");//訂閱者們拿報紙
    }

    public void Subscribe(INewsPaperBox newsPaperBox)
    {
        subscribers.Add(newsPaperBox);//放報紙
    }
}

public class MilkSender
{
    // 介面實作 
    protected ArrayList subscribers = new ArrayList();

    public void SendMilk()
    {
        foreach (IMilkBox milkBox in subscribers)
            milkBox.PutMilkIn(" 牛奶 ");
    }
    public void Subscribe(IMilkBox milkBox)
    {
        subscribers.Add(milkBox);
    }
}
class Program
{
    // 功能的實作 
    public static void Main(string[] args)
    {
        // 介面實作 
        MilkSender ms = new MilkSender();
        NewsPaperSender nps = new NewsPaperSender();
        Subscriber s1 = new Subscriber(" 張三 ");
        Subscriber s2 = new Subscriber(" 李四 ");
        Subscriber s3 = new Subscriber(" 王五 ");
        ms.Subscribe(s1);
        ms.Subscribe(s2);
        nps.Subscribe(s2);
        nps.Subscribe(s3);
        ms.SendMilk();
        nps.SendNewsPaper();
        Console.ReadLine();
    }
}
using System;

delegate void WorkStarted();
delegate void WorkProgressing();
delegate int WorkCompleted();

class Worker
{
    public void DoWork()
    {
        Console.WriteLine("作業: 作業開始");
        if (started != null) started();
        Console.WriteLine("作業: 作業進行中");
        if (progressing != null) progressing();
        Console.WriteLine("作業: 作業完成");
        if (completed != null)
        {
            foreach (WorkCompleted wc in completed.GetInvocationList())
            {
                wc.BeginInvoke(null, null);
            }
        }
    }
    public event WorkStarted started;
    public event WorkProgressing progressing;
    public event WorkCompleted completed;
}

class Boss
{
    public int WorkCompleted()
    {
        Console.WriteLine("Better...");
        return 4; /* 總分為10 */
    }
}

class Family
{
    public int WorkCompleted()
    {
        Console.WriteLine("快回家吧,我們想你了!");
        return 10;
    }
}

class Universe
{
    public static void WorkStarted()
    {
        Console.WriteLine("universe know the start of work");
    }
    public static void WorkProgressing()
    {
        Console.WriteLine("universe know the progressing of work");
    }
    public static int WorkCompleted()
    {
        Console.WriteLine("universe say good!");
        return 8;
    }
}

class A
{
    static void Main()
    {
        Worker peter = new Worker();
        Boss boss = new Boss();
        Family f = new Family();
        peter.started += new WorkStarted(Universe.WorkStarted);
        peter.progressing += new WorkProgressing(Universe.WorkProgressing);
        peter.completed += new WorkCompleted(f.WorkCompleted);
        peter.completed += new WorkCompleted(Universe.WorkCompleted);
        peter.completed += new WorkCompleted(boss.WorkCompleted);
        peter.DoWork();
        Console.WriteLine("Main: 工人作業完成");
        Console.ReadLine();
    }
}

14、實體建構式

[建構式修飾符] 識別符號([引數串列] )
[ : base ( [引數串列] ) ] [ : this ( [引數串列] ) ]
{
建構式陳述句塊
}

using System;
namespace ConstructorExp
{
    class Base
    {
        public Base(int x)
        {
            Console.WriteLine("Base.Base(int)");//4
            this.x = x;
        }
        private static int InitX()
        {
            Console.WriteLine("Base.InitX()"); //3
            return 1;
        }
        public int x = InitX();
    }
    class Derived : Base
    {
        public Derived(int a)
            : base(a)
        {
            Console.WriteLine("Derived.Derived(int)"); //5
            this.a = a;
        }
        public Derived(int a, int b)
            : this(a)
        {
            Console.WriteLine("Derived.Derived(int,int)"); //6        
            this.b = b;
        }
        private static int InitA()
        {
            Console.WriteLine("Derived.InitA()");//1
            return 3;
        }
        private static int InitB()
        {
            Console.WriteLine("Derived.InitB()");//2
            return 4;
        }
        public int a = InitA();
        public int b = InitB();
    }
    class Program
    {
        static void Main(string[] args)
        {
            Derived b = new Derived(1, 2);
            Console.ReadLine();
        }
    }
}

15、靜態建構式

[靜態建構式修飾符] 識別符號()
{
靜態建構式體
}
在這里插入圖片描述

16、解構式

~識別符號()
{
解構式體
}
在這里插入圖片描述
在這里插入圖片描述

17、運算子多載

在這里插入圖片描述

  • C#要求以靜態方式宣告運算子多載
  • 編譯器不能改變二元運算子的引數順序
 //二元運算子“+”多載
public static Complex operator +(Complex a, Complex b) {
        return new Complex(a.r + b.r, a.v + b.v);
}
//一元運算子“-”多載
public static Complex operator -(Complex a) {
        return new Complex(-a.r, -a.v);
}
//一元運算子“++”多載
public static Complex operator ++(Complex a) {
        double r = a.r + 1;
        double v = a.v + 1;
        return new Complex(r, v);
}

18、用戶定義的資料型別轉換

  • 隱式型別轉換
    在這里插入圖片描述
  • 顯示型別轉換
    在這里插入圖片描述
//隱式型別轉換,實作double型別轉換為Square
public static implicit operator Square(double s) {
	Console.WriteLine("隱式型別轉換,實作double型別轉換為Square");
	return new Square(s);
}
//顯式型別轉換,實作Square型別轉換為double
public static explicit operator double(Square s) {
	Console.WriteLine("顯式型別轉換,實作Square型別轉換為double");
	return s.side;
}

19、方法的引數(引數陣列params的使用)

在這里插入圖片描述

public void swap2(ref int x, ref int y)
{
	int temp;
	temp = x;
	x = y;
	y = temp;
}
A a = new A();
a.swap2(ref xx, ref yy);

在這里插入圖片描述
在這里插入圖片描述

public class A {
        public void MaxMin(out int max, out int min, params int[] a) {
            if (a.Length == 0) {
                max = min = -1;
                return;
            }
            max = min = a[0];
            for (int i = 1; i < a.Length; i++) {
                if (a[i] > max) max = a[i];
                if (a[i] < min) min = a[i];
                a[i]++;
            }
        }
    }
A a = new A();
int maxNumber, minNumber;
a.MaxMin(out maxNumber, out minNumber, 48, 92, 62, 52, 78);
Console.WriteLine("Max={0},Min={1}", maxNumber, minNumber);

第四章 WinForm程式設計

Button

常用屬性
Text
按鈕上顯示的文本包含在Text屬性中,如果文本超
出按鈕寬度,則換到下一行,可以包含訪問鍵,
FlatStyle
如果把按鈕樣式設定為Popup,則按鈕就顯示為平
面,直到用戶把滑鼠指標移動到它上面為止,此
時,按鈕會彈出,顯示為正常的3D外觀,
Enabled
設定為false,按鈕會灰顯,單擊它不起任何作用
Image
可以指定在一個按鈕上顯示的影像(位圖,圖示等)
ImageAlign
設定按鈕的影像在什么地方設定
ImageList
AcceptButton
在任何Windows表單上都可以指定某個Button控制元件為接受按鈕,每當用戶按Enter鍵時,即單擊默認按鈕,而不管當前表單上其他哪個控制元件具有焦點
CancelButton
每當用戶按ESC鍵時,即單擊取消按鈕,而不管當前表單上其他哪個控制元件具有焦點
HelpButton
獲取或設定一個值,該值指示是否應在表單的標題框中顯示“幫助”按鈕,
常用事件
Click
該控制元件不支持雙擊事件

TextBox

常用屬性
CausesValidation
該屬性設定為true,且該控制元件獲得了焦點時,會引發兩個事件:validating和validated,可以處理這些事件,以便驗證失去焦點的控制元件中資料的有效性,這可能使控制元件永遠都不能獲得焦點
CharacterCasing
表示文本框是否會改變輸入文本的大小寫Lower、Normal、Upper
MaxLength
指定輸入到文本框中的最大字符長度
Multiline
表示該控制元件是一個多行控制元件
PasswordChar
指定是否用密碼字符替換在單行文本框中輸入的字符
ReadOnly
表示文本是否為只讀
ScrollBars
指定多行文本框是否顯示滾動條
SelectedText
在文本框中顯示的文本
SelectionLength
在文本中選擇的字符數
SelectionStart
文本框中被選中文本的開頭
WordWrap
指定在多行文本框中,如果一行的寬度超出了控制元件的寬度,其文本是否應自動換行
AcceptsReturn
獲取或設定一個值,該值指示在多行 TextBox控制元件中按 Enter 鍵時,是在控制元件中創建一行新文本還是激活表單的默認按鈕,
AcceptsTab
文本框的常用方法
Clear
AppendText
Copy
Cut
Paste
Select
SelectAll
文本框的常用事件
焦點事件
Enter
Leave
Validating
Validated
鍵事件
KeyDown
KeyPress
KeyUp
TextChanged事件
文本框的內容發生變化時觸發該事件

RadioButton

RadioButton控制元件的屬性
Appearance
如果將該屬性設定為Appearance.Button,則RadioButton的外觀可以像命令按鈕一樣
AutoCheck
該屬性設定為true, 用戶單擊單選按鈕時,自動被選中或取消選中,否則,必須在Click事件處理程式中手工設定Checked屬性
Checked
表示控制元件是否被選中的標記
CheckAlign
可以改變單選按鈕的對齊形式,默認是
ContentAlignment.MiddleLeft
RadioButton控制元件的事件
CheckedChanged
當RadioButton的選中狀態改變時,引發該事件
Click
每次單擊RadioButton時引發該事件,連續單擊RadioButton兩次或多次只改變checked屬性一次,如果被單擊按鈕的AutoCheck屬性是false,則該按鈕根本不會被選中,只引發click事件

CheckBox

CheckBox控制元件的屬性
CheckState
與RadioButton不同,CheckBox有三種狀態:Checked、Indeterminate、Unchecked,復選框的狀態是Indeterminate時,表示復選框的當前值是無效的或者在當前環境下沒有意義
ThreeState
當屬性為false時,用戶不能把CheckState屬性改為Indeterminate
CheckBox控制元件的事件
CheckedChanged
當復選框的Checked屬性改變時,就引發該事件,注意在復選框中,當ThreeState屬性為true時,單擊復選框不會改變Checked屬性,在復選框由Checked變為indeterminate狀態時,就會出現這種情況
CheckStateChanged
當CheckState屬性改變時,引發該事件

RichTextBox

常用屬性
CanRedo
如果上一個被撤銷的操作可以使用Redo恢復,該屬性為true
CanUndo
如果可以在RichTextBox上撤銷上一個操作,該屬性為true,可用于TextBox
RedoActionName
該屬性包含通過Redo方法執行的操作名稱
DetectUrls
該屬性設定為true,可以使控制元件檢測URL并格式化它們
Rtf
對應于Text屬性,但包含RTF格式的文本
SelectedRtf
使用該屬性可以獲取或設定控制元件中被選中的RTF格式文本,該文本會保留原有的格式化資訊
SelectedText
使用該屬性可以獲取或設定控制元件中被選中的文本,但所有的格式化資訊都會丟失
SelectionAlignment
表示選中文本的對齊方式,可以是Center、Left或right
SelectionBullet
使用該屬性可以確定選中的文本是否格式化為專案符號的格式
BulletIndent
指定專案符號的縮進像素值
SelectionColor
該屬性可以修改選中文本的顏色
SelectionFont
可以修改選中文本的字體
SelectionLength
可以設定或獲取選中文本的長度
SelectionType
該屬性包含選中文本的資訊,可以確定是選擇了一個或多個OLE物件還是僅選擇了文本
ShowSelectionMargin
該屬性設定為true,在RichTextBox的左邊會出現一個頁邊距,將使用戶更易于選擇文本
UndoActionName
如果用戶選擇撤銷某個動作,該屬性將獲取該動作的名稱
SelectionProtected
該屬性設定為true,可以指定不修改文本的某些部分
RichTextBox控制元件的事件
LinkedClick
在用戶單擊文本中的鏈接時,引發該事件
Protected
在用戶嘗試修改被保護的文本時,引發該事件
SelectionChanged
在選中文本發生變化時,引發該事件,

ListBox

常用屬性
SelectedIndex
表示選中選項的基于0的索引,若選中多項,則是第一項的索引
ColumnWidth
在包含多個列的串列框中指定列的寬度
Items
包含串列框中的所有選項
MultiColumn
獲取和設定串列框中列的數目
SelectedIndices
串列框中選中的多項基于0的索引集合
SelectedItem
指選中的選項,若 選中多項,則指第一項
SelectedItems
包含當前選中的所有選項
Sorted
該屬性設定為true,可使串列框對它所包含的選項按照字母順序排序
Text
設定該屬性,將搜索匹配該文本的選項,并選擇該選項;獲取該屬性,回傳的值是串列中第一個選中的選項
SelectionMode
可以使用ListSelectionMode列舉中的4種選擇模式
None 不能選擇任何選項
One 一次只能選擇一個選項
MultiSimple 可選擇多個選項
MultiExtended 可選擇多個選項,用戶可使用Ctrl、Shift、和箭頭鍵進行選擇,

ComboBox

常用方法
public void BeginUpdate ()
當將多項一次一項地添加到 ComboBox 時維持性能,
public void EndUpdate ()
在 BeginUpdate 方法掛起繪制后,該方法恢復繪制 ComboBox 控制元件,

TreeView

ListView

常用屬性
Activation
該屬性可以控制用戶在串列視圖中激活選項的方式
Standard 用戶為自己的機器選擇的值
OneClick 單擊一個選項,激活它
TwoClick 雙擊一個選項,激活它
Alignment
該屬性可以控制串列視圖中選項對齊的方式
Default 如果用戶拖放一個選項,它將仍位于拖動前的位置
Left 選項與ListView控制元件的左邊界對齊
Top 選項與ListView控制元件的頂邊界對齊
SnapToGrid ListView控制元件包含一個不可見的網格,選項都放在該網格中
AllowColumnReorder
該屬性設定為true,允許用戶修改串列視圖中列順序
AutoArrange
該屬性設定為true,選項會自動根據Alignment屬性排序
當View屬性取為LargeIcon或SmallIcon時才有意義
CheckBoxes
該屬性設定為true,串列視圖中的每個選項會在其左邊顯示一個復選框,當View屬性取為Details或List時才有意義
CheckedIndices, CheckedItems
選中索引和選項的集合
Columns 列集合
FocusedItem
串列視圖中有焦點的選項
FullRowSelect
該屬性為true,單擊選項,整行都被選中
GridLines
該屬性設定為true,會在行和列之間繪制網格線,
只有View取Details才有意義
HeaderStyle
Clickable NonClickable None
HoverSelection
該屬性設定為true,用戶可以把指標放在串列視圖的一個選項上以選擇它
Items
LabelEdit
該屬性設定為true,用戶可以在Details視圖下編輯第一列的內容
LabelWrap
該屬性設定為true,標簽會自動換行,以顯示所有的文本
LargeImageList
包含大影像,可以在View屬性為LargeIcon時使用
MultiSelect
該屬性設定為true,用戶可以選擇多個選項
Scrollable
該屬性設定為true,顯示滾動條
SelectedIndices, SelectedItems
選中索引和選項的集合
SmallImageList
Sorting
Ascending
Descending
None
StateImageList
包含影像的模板,這些影像模板可用作LargeImageList和SmallImageList影像的覆寫圖,表示定制的狀態
TopItem
回傳串列視圖頂部的選項
View
LargeIcon
SmallIcon
List
顯示小圖示,但總是顯示在單列中
Details
在多列中顯示項
Tile
顯示一個大圖示和一個標簽,在圖示的右邊顯示子項資訊
HideSelection
指示當控制元件沒有焦點時,該控制元件選定的項是否保持突出顯示
ListView控制元件的方法
public void BeginUpdate ( )
該方法告訴串列視圖停止更新,直到呼叫EndUpdate為止
public void EndUpdate ()
呼叫該方法,串列視圖會顯示出所有選項
public void Clear ()
public void EnsureVisible ( int index )
串列視圖會滾動以顯示指定索引的選項
public ListViewItem GetItemAt ( int x, int y )
回傳串列視圖中位于x,y的選項
ListView控制元件的事件
AfterLabelEdit
編輯了標簽后,引發該事件
BeforeLabelEdit
用戶開始編輯標簽前,引發該事件
ColumnClick
單擊一個列時,引發該事件
ItemActivate
激活一個選項時,引發該事件

PictureBox

用于顯示位圖(.bmp)、GIF(.gif)、JPEG(.jpg)、圖元檔案(.wmf)、圖示(.ico)格式的圖形
常用屬性
Image
指定顯示的圖片
SizeMode
控制影像和控制元件彼此適合的方式
Normal 將控制元件的左上角與控制元件的左上角對齊
AutoSize 調整控制元件的大小以適合其顯示的圖片
CenterImage 圖片在控制元件內居中
StretchImage 拉伸所顯示的圖片以適合控制元件

選單欄

ToolStripMenuItem
常用屬性
ShortcutKeys
獲取或設定與 ToolStripMenuItem 關聯的快捷鍵,
Image
獲取或設定顯示的影像
Checked
表示選單是否被選中
CheckOnClick
該屬性為true,如果選單項左邊的復選框沒有打上標記,就打上標記,如果該復選框已打上標記,就清除該標記,否則,該標記就被一個影像替代,
Enabled
該屬性設定為false,選單項就會灰顯,不能被選中
DropDownItems
回傳一個項集合,用作與選單項相關的下拉選單
事件
Click
用戶單擊選單項時引發該事件
CheckedChanged
單擊帶CheckedOnClick屬性的選單項時,引發該事件

工具列

ToolStrip
常用屬性
GripStyle
該屬性控制移動手柄是可見還是隱藏
ToolStripGripStyle.Hidden Visible
LayoutStyle
控制工具列上的項如何顯示,默認水平顯示
ToolStripLayoutStyle.Flow 按水平或垂直方向排列
HorizontalStackWithOverflow 按水平方向進行布局且必要時會溢位
StackWithOverflow 按自動方式進行布局
Table 布局方式為左對齊
VerticalStackWithOverflow 按垂直方向進行布局,在控制元件中居中且必要時會溢位
Items
工具列中所有項的集合
ShowItemToolTip
確定是否顯示工具列上某項的工具提示
Stretch
該屬性設定為true,工具列會占據容器的總長
ToolStrip的項
ToolStripButton
表示一個按鈕,用于帶文本和不帶文本的按鈕
ToolStripLabel
表示一個標簽,還可以顯示影像
ToolStripSplitButton
表示一個右端帶有下拉按鈕的按鈕
ToolStripDropDownButton
控制元件具有下拉陣列影像,單擊控制元件的任一部分,都可以打開選單部分
ToolStripComboBox
組合框
ToolStripProgressBar
進度條
ToolStripTextBox
文本框
ToolStripSeperator
為各個項創建水平或垂直分隔符

狀態欄

StatusStrip中可以使用ToolStripDropDownButton、ToolStripProgressBar、ToolStripSplitButton
StatusStripStatusLabel
AutoSize
DoubleClickEnable
可以指定是否引發DoubleClick事件

OpenFileDialog

InitialDirectory屬性
檔案對話框顯示的初始目錄
默認情況下,對話框將打開用戶在上一次運行應用
程式時打開的目錄
默認值是一個空串,表示用戶的“我的檔案”目錄
Filter屬性
設定檔案過濾器,定義用戶可以選擇打開的檔案型別
每個部分需要有兩個字串,第一個字串定義要在文本框中顯示的文本,第二個字串用于指定要在對話框中顯示的檔案擴展名
FilterIndex屬性
指定串列框中的默認選項, 基于1
ValidateNames屬性
檢查用戶輸入的檔案名,看其是否是一個有效的檔案名,
該屬性設定為true,可以使用CheckFileExists屬性驗證
檔案的有效性,使用CheckPathExists屬性驗證路徑的有效性
FileName屬性
包含在檔案對話框中選定檔案名的字串
Multiselect屬性
該屬性設定為true,用戶可以選中多個檔案
FileNames屬性
包含所有選中檔案名的字串,包含的檔案順序與
選中它們的順序相反,
OpenFileDialog的專用屬性
ShowReadOnly屬性
指示對話框是否包含只讀復選框
ReadOnlyChecked屬性
指示是否選定只讀復選框
OpenFileDialog的常用方法
public Stream OpenFile ()
打開用戶選定的具有只讀權限的檔案

SaveFileDialog

常用屬性
AddExtension
指示如果用戶省略擴展名,對話框是否自動在檔案名中添加擴展名,
DefaultExt
設定檔案默認擴展名
CreatePrompt
指示如果用戶指定不存在的檔案,對話框是否提示用戶允許創建該檔案
OverwritePrompt
指示如果用戶指定的檔案名已存在,Save As 對話框是否顯示警告,

FontDialog

常用屬性
AllowVectorFonts
指示是否可在字體串列中選擇矢量字體,默認為true
AllowVerticalFonts
指示是否可在字體串列中選擇垂直字體,默認為true
FixedPitchOnly
該屬性設定為true,僅在字體串列中顯示固定大小的字體,默認為false
MaxSize
定義用戶可以選擇的最大字號
MinSize
定義用戶可以選擇的最小字號
ShowApply
該屬性設定為true,顯示Apply按鈕
ShowEffects
該屬性設定為true,可以選擇Strikeout和Underline復選框來處理字體
ShowColor
該屬性設定為true,在對話框中顯示Color選項
AllowScriptChange
該屬性設定為false,可防止用戶改變字體的腳本
FontMustExist
指示對話框是否指定當用戶試圖選擇不存在的字體或樣式時的錯誤條件
Apply事件
單擊Apply按鈕觸發的事件

ColorDialog

2、掌握事件處理程序

不想掌握

第五章 流

1、 FileStream

  • 表示在磁盤或網路路徑上指向文件的流,提供了在檔案中讀寫位元組的方法
  • 構造方法

public FileStream (string path, FileMode mode)
public FileStream(string path, FileMode mode, FileAccess access)

public override long Seek(long offset, SeekOrigin origin)
//offset為檔案指標以位元組為單位的移動距離
//origin為開始計算的起始位置
//SeekOrigin.Begin Current End
public override int Read(byte[] array, int offset, int count)
//array為位元組陣列
//offset為位元組陣列中開始寫入資料的位置
//count指定從檔案中讀出多少位元組
public override void Write(byte[] array, int offset, int count)
//使用從緩沖區讀取的資料將位元組塊寫入該流
byte[] byData = new byte[200];
char[] charData = new char[200];
try
{
    FileStream aFile = new FileStream("E:/程式/f2.java",
                                             FileMode.Open);
    aFile.Seek(90, SeekOrigin.Begin);
    aFile.Read(byData, 0, 200);
}

2、 StreamWriter與StreamReader

  • StreamWriter的構造方法

public StreamWriter (string path)
public StreamWriter (string path,bool append)
(append 為false,則創建一個新檔案,或截取現有檔案并打開它)
(append 為true,則打開檔案,保留原有資料,如果找不到檔案,則創建一個新檔案)
public StreamWriter (Stream stream)

FileStream aFile = new FileStream(“Log.txt”, FileMode.CreateNew);
StreamWriter sw = new StreamWriter(aFile);
  • StreamWriter的Write和WriteLine方法
public override void Write(string value)
//將字串寫入流,引數除字串外可以是任何基本資料型別
public virtual void WriteLine(string value)
//將字串寫入流并換行,引數除字串外可以是任何基本資料型別
try
{
    FileStream aFile = new FileStream("E:/Log.txt“,    

                                     FileMode.OpenOrCreate);
    StreamWriter sw = new StreamWriter(aFile);
    bool truth = true;
    sw.WriteLine("Hello to you.");
    sw.WriteLine("It is now {0} and things are looking  

     good.",  DateTime.Now.ToLongDateString());

    sw.Write("More than that,");
    sw.Write(" it's {0} that C# is fun.", truth);
    sw.Close();
}

在這里插入圖片描述

  • StreamReader的構造方法

public StreamReader (Stream stream)
public StreamReader (string path)

  • StreamReader的Read、ReadLine、ReadToEnd方法
public override int Read()
//讀取輸入流中的下一個字符,到達流末尾則回傳 - 1
public override int Read(char[] buffer, int index, int count)
//從index開始,將當前流中的最多count個字符讀入buffer中
public override string ReadLine()
//從當前流中讀取一行字符,并將資料作為字串回傳
public override string ReadToEnd()
//從流的當前位置到末尾讀取流

3、 BinaryReader和BinaryWriter

BinaryReader
常用函式
public virtual XXX readXXX() //對各種基本資料型別的讀取
public virtual int Read()
public virtual int Read(byte[] buffer, int index, int count)
public virtual int Read(char[] buffer, int index, int count)
建構式
public BinaryReader (Stream input)
public BinaryReader(Stream input, Encoding encoding)
BinaryWriter
常用函式
public virtual void Write(XXX xx)
public virtual void Write(byte[] buffer, int index, int count)
public virtual void Write(char[] chars, int index, int count)
建構式
protected BinaryWriter ()
public BinaryWriter (Stream output)
public BinaryWriter (Stream output, Encoding encoding)

4、 物件的串行化

  • .NETFramework在System.Runtime.Serialization和System.Runtime.Serialization.Formatters命名空間中提供了串行化物件的基礎架構
  • System.Runtime.Serialization.Formatters.Binary在該命名空間中包含的BinaryFormatter類能把物件串行化為二進制資料,把二進制資料串行化為物件
  • System.Runtime.Serialization.Formatters.Soap在該命名空間中包含的SoupFormatter類能把物件串行化為SOAP格式的XML資料,把SOAP格式的XML資料串行化為物件

IFormatter介面
void Serialize(Stream serializationStream, Object graph)
將物件或具有給定根的物件圖形序列化為所提供的流,
Object Deserialize(Stream serializationStream)
反序列化所提供流中的資料并重新組成物件圖形

IFormatter serializer = new BinaryFormatter();
FileStream saveFile = new FileStream("E:/Products.bin",
                                       FileMode.Create, FileAccess.Write);
serializer.Serialize(saveFile, products);
saveFile.Close();

FileStream loadFile = new FileStream("E:/Products.bin",
                                       FileMode.Open, FileAccess.Read);
List<Product> savedProducts =
                         serializer.Deserialize(loadFile) as List<Product>; 
loadFile.Close();

5、監控檔案結構FileSystemWatcher

在這里插入圖片描述

啟用FileSystemWatcher物件之前必須設定的屬性
Path
設定要監控的檔案位置或目錄
NotifyFilter
NotifyFilters列舉值規定在被監控的檔案內要監控哪些內容
Filter
監控檔案的過濾器

必須為Changed、Created、Deleted和Renamed撰寫事件處理程式
當修改與Path、NotifyFilter和Filter屬性匹配的檔案或目錄時,就引發每一個事件
將EnableRaisingEvents屬性設定為true,就可以開始監控作業

private FileSystemWatcher watcher;
private delegate void UpdateWatchTextDelegate(string newText);

public Form1()
{
    InitializeComponent();
    this.watcher = new System.IO.FileSystemWatcher();
    this.watcher.Deleted +=
       new System.IO.FileSystemEventHandler(this.OnDelete);
    this.watcher.Renamed +=
       new System.IO.RenamedEventHandler(this.OnRenamed);
    this.watcher.Changed +=
       new System.IO.FileSystemEventHandler(this.OnChanged);
    this.watcher.Created +=
       new System.IO.FileSystemEventHandler(this.OnCreate);
    DirectoryInfo aDir = new DirectoryInfo(@"C:\\FileLogs");
    if (!aDir.Exists)
        aDir.Create();
}
private void cmdWatch_Click(object sender, EventArgs e)//設定屬性
{
    watcher.Path = Path.GetDirectoryName(txtLocation.Text);
    watcher.Filter = Path.GetFileName(txtLocation.Text);
    watcher.NotifyFilter = NotifyFilters.LastWrite |
       NotifyFilters.FileName | NotifyFilters.Size;
    lblWatch.Text = "Watching " + txtLocation.Text;
    watcher.EnableRaisingEvents = true;
}
public void OnChanged(object source, FileSystemEventArgs e) { }
public void OnRenamed(object source, RenamedEventArgs e) { }
public void OnDelete(object source, FileSystemEventArgs e) { }
public void OnCreate(object source, FileSystemEventArgs e) { }

第六章 多執行緒技術

1、 執行緒的建立與啟動

//public Thread (ThreadStart start)指定入口
Thread compressThread = new Thread(entryPoint);
static void DoCompress(){
	//代碼
}
ThreadStart entryPoint = new ThreadStart(DoCompress);

2、 執行緒的常用方法,Start、Join、Sleep,

//啟動執行緒,即給執行緒分配除處理器之外的系統資源并執行各種安全性檢查,
compressThread.Start();//在呼叫該方法后,新執行緒并不是處于Running狀態,而是處于Unstarted狀態

compressThread.Suspend();//使執行緒處于阻塞狀態
compressThread.Resume();//恢復被掛起的執行緒,進入就緒狀態
compressThread.Abort();//中止執行緒,永久洗掉不能重新啟動
compressThread.Join();//進入阻塞,等待呼叫該方法執行緒執行完畢
compressThread.Sleep(int millisecondsTimeout);//睡會兒,睡醒就緒

3、 Thread類的常用屬性 CurrentThread、Name、Priority

CurrentThread
獲取當前正在運行的執行緒
Thread myOwnThread = Thread.CurrentThread;

Name
執行緒的名稱

Priority
指示執行緒的調度優先級
從高到低為:(同級時間片輪轉)
ThreadPriority.Highest
ThreadPriority.AboveNormal
ThreadPriority.Normal
ThreadPriority.BelowNormal
ThreadPriority.Lowest

4、 給執行緒傳遞資料

Thread類有一個帶引數的委托型別的多載形式,這個委托的定義如下:

[ComVisibleAttribute(false)]
public delegate void ParameterizedThreadStart(Object obj)

這個Thread類的構造方法的定義如下:

public Thread(ParameterizedThreadStart start);

下面的代碼使用了這個帶引數的委托向執行緒傳遞一個字串引數:

public static void myStaticParamThreadMethod(Object obj)  
{  
	Console.WriteLine(obj);  
}  
 
static void Main(string[] args)  
{  
	Thread thread = new Thread(myStaticParamThreadMethod);  
	thread.Start("通過委托的引數傳值");  
}  

要注意的是,如果使用的是不帶引數的委托,不能使用帶引數的Start方法運行執行緒,否則系統會拋出例外,但使用帶引數的委托,可以使用thread.Start()來運行執行緒,這時所傳遞的引數值為null,

也可以定義一個類來傳遞引數值,如下面的代碼如下

class MyData  
{  
	private String d1;  
	private int d2;  
	public MyData(String d1, int d2)  
	{  
		this.d1 = d1;  
		this.d2 = d2;  
	}  
	public void threadMethod()  
	{  
		Console.WriteLine(d1);  
		Console.WriteLine(d2);  
	}  
}  
 
MyData myData = new MyData("abcd",1234);  
Thread thread = new Thread(myData.threadMethod);  
thread.Start();  

如果使用定義的MyThread類,傳遞引數會顯示更簡單,代碼如下:

class NewThread : MyThread  
{  
    private String p1;  
    private int p2;  
    public NewThread(String p1, int p2)  
    {  
        this.p1 = p1;  
        this.p2 = p2;  
    }  
 
    override public void run()  
    {  
        Console.WriteLine(p1);  
        Console.WriteLine(p2);  
    }  
}  
 
NewThread newThread = new NewThread("hello world", 4321);  
newThread.start();  

5、后臺執行緒

在這里插入圖片描述

public static void myStaticThreadMethod()  
{  
    Thread.Sleep(3000);  
}  
 
Thread thread = new Thread(myStaticThreadMethod);  
// thread.IsBackground = true;  
thread.Start();  
  • 如果運行上面的代碼,程式會等待3秒后退出,如果將注釋去掉,將thread設成后臺執行緒,則程式會立即退出,
  • 要注意的是,必須在呼叫Start方法之前設定執行緒的型別,否則一但執行緒運行,將無法改變其型別,

6、執行緒池

ThreadPool

  • 執行緒池是可以用來在后臺執行多個任務的執行緒集合,使主執行緒可以自由地異步執行其它任務
  • 該類會在需要時增減池中執行緒的個數,直到最大的執行緒數,
  • 池中的最大執行緒數是可配置的
  • 如果有更多的作業要處理,而執行緒池中執行緒的使用也到了極限,最新的作業就要排隊,必須等待執行緒完成其任務
  • 執行緒池中的每個執行緒都使用默認的堆疊大小,以默認的優先級運行,并處于多執行緒單元中
  • 如果執行緒池執行緒都始終保持繁忙,但佇列中包含掛起的作業,則執行緒池將在一段時間之后創建另一個輔助執行緒
  • 執行緒池適合于執行一些需要多個執行緒的任務,使用執行緒池可以優化任務的執行程序,提高吞吐量;如果應用程式需要對執行緒進行特定的控制,則不適合使用執行緒池,需要創建并管理自己的執行緒
  • 每個行程都有且僅有一個執行緒池,當行程啟動時,執行緒池不會自動創建,只有第一次將回呼方法排入佇列時才會創建執行緒池,
  • 執行緒池通常用于服務器應用程式,每個傳入請求都將分配給執行緒池中的一個執行緒,因此可以異步處理請求,而不會占用主執行緒,也不會延遲后續請求的處理

ThreadPool常用方法
void GetMaxThreads(out int workerThreads,out int completionPortThreads)
//檢索可以同時處于活動狀態的執行緒池請求的數目,所有大于此數目的請求將保持排隊狀態,直到執行緒池執行緒變為可用
-bool QueueUserWorkItem ( WaitCallback callback )
-public delegate void WaitCallback(Object state)
將方法排入佇列以便執行,此方法在有執行緒池執行緒變得可用時執行 ,執行緒池收到請求后會從池中選擇一個執行緒來呼叫該方法,如果執行緒池還沒有運行,就會創建一個執行緒池,并啟動第一個執行緒,如果執行緒池已經在運行,且有一個空閑執行緒來完成該任務就把該作業傳遞給這個執行緒

using System;
using System.Threading;

namespace Wrox.ProCSharp.Threading
{
    class Program
    {
        static void Main()
        {
            int nWorkerThreads;
            int nCompletionPortThreads;
            ThreadPool.GetMaxThreads(out nWorkerThreads, out nCompletionPortThreads);
            Console.WriteLine("Max worker threads: {0}, I/O completion threads: {1}", nWorkerThreads, nCompletionPortThreads);

            for (int i = 0; i < 7; i++)
            {
                ThreadPool.QueueUserWorkItem(JobForAThread);

            }

            Thread.Sleep(30000);
            Console.ReadLine();
        }


        static void JobForAThread(object state)
        {
            for (int i = 0; i < 4; i++)
            {
                Console.WriteLine("loop {0}, running inside pooled thread {1}", i,
                   Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(50);
            }

        }
    }

}

7、執行緒同步

  • (1)System.Threading.Monitor類提供的靜態方法 Enter、Exit、Wait、Pulse、PulseAll
public static void Enter ( Object obj ) 
//在指定物件上獲取排它鎖
public static void Exit ( Object obj )  
//釋放指定物件上的排它鎖
public static bool Wait ( Object obj )
//釋放物件上的鎖并阻塞當前執行緒,直到它重新獲取該鎖, 
public static void Pulse ( Object obj ) 
//通知等待佇列中的執行緒鎖定物件狀態的更改,
public static void PulseAll ( Object obj ) 
//通知所有的等待執行緒物件狀態的更改
  • (2)執行緒同步的幾種方法:

1使用Lock(鎖定物件) { 互斥代碼塊 } 實作互斥

//C#的lock關鍵字提供了與Monitor.Enter和Monitor.Exit同樣的功能
lock  ( obj )
{
    ...
}

2設Mutex類物件為mut,在互斥代碼塊前使用mut.WaitOne( ),在互斥代碼塊后使用mut.ReleaseMutex( )

典型的使用Mutex同步需要完成三個步驟的操作:1.打開或者創建一個Mutex實體;2.呼叫WaitOne()來請求互斥物件;3.最后呼叫ReleaseMutex來釋放互斥物件,

if ( Mut.WaitOne() )
{
     try
    {
        ……
     }
     finally
    {
        mut.ReleaseMutex( );
    }
}
else
{
      ……
}

3在互斥代碼塊前使用Monitor.Enter(鎖定物件),在互斥代碼塊后使用Monitor.Exit(鎖定物件)

Monitor.Enter(obj);
try
{
……
}
finally
{
Monitor.Exit(obj);
}

4使用Interlocked
在這里插入圖片描述
在這里插入圖片描述
5等待句柄
在這里插入圖片描述

6使用Semphore
在這里插入圖片描述

static void Main()
{
	int threadCount = 6;
	int semaphoreCount = 4;
	var semaphore = new SemaphoreSlim(semaphoreCount, semaphoreCount);
	var threads = new Thread[threadCount];
	for (int i = 0; i < threadCount; i++)
	{
		threads[i] = new Thread(ThreadMain);
		threads[i].Start(semaphore);
	}
	for (int i = 0; i < threadCount; i++)
	{
		threads[i].Join();
	}
	Console.WriteLine("All threads finished");
	Console.ReadLine();
}

static void ThreadMain(object o)
{
	SemaphoreSlim semaphore = o as SemaphoreSlim;
	Trace.Assert(semaphore != null, "o must be a Semaphore type");
	bool isCompleted = false;
	while (!isCompleted)
	{
		if (semaphore.Wait(600))
		{
			try
			{
				Console.WriteLine("Thread {0} locks the semaphore",
				Thread.CurrentThread.ManagedThreadId);
			T	hread.Sleep(2000);
			}
			finally
			{
				semaphore.Release();
				Console.WriteLine("Thread {0} releases the semaphore",
				Thread.CurrentThread.ManagedThreadId);
				isCompleted = true;
			}
		}
		else
		{
			Console.WriteLine("Timeout for thread {0}; wait again",
			Thread.CurrentThread.ManagedThreadId);
		}
}

7 ReaderWriterLockSlim
在這里插入圖片描述

try
{
	while (!rwl.TryEnterWriteLock(50))
	{
		Console.WriteLine("Writer {0} waiting for the write lock",writer);
		Console.WriteLine("current reader count: {0}",rwl.CurrentReadCount);
	}
	Console.WriteLine("Writer {0} acquired the lock", writer);
	for (int i = 0; i < items.Count; i++)
	{
		items[i]++;
		Thread.Sleep(50);
	}
	Console.WriteLine("Writer {0} finished", writer);
}
finally
{
	rwl.ExitWriteLock();
}

8、任務Task

  • 創建Task物件
class Program
{
    static void DownLoad(object str)
    {
        Console.WriteLine("DownLoad Begin ID = " + Thread.CurrentThread.ManagedThreadId + " " + str);
        Thread.Sleep(1000);
        Console.WriteLine("DownLoad End");
    }
    static void Main(string[] args)
    {
        //創建任務
        Task task = new Task(DownLoad, "人民日報");
        //啟動任務
        task.Start();
        Console.WriteLine("Main");   
        Console.ReadKey();
    }
}
  • 任務工廠TaskFactory
class Program
{
    static void DownLoad(object str)
    {
        Console.WriteLine("DownLoad Begin ID = " + Thread.CurrentThread.ManagedThreadId + " " + str);
        Thread.Sleep(1000);
        Console.WriteLine("DownLoad End");
    }
    static void Main(string[] args)
    {
        //創建任務工廠
        TaskFactory taskFactory = new TaskFactory();
        //開始新的任務
        taskFactory.StartNew(DownLoad, "紐約時報");
        Console.WriteLine("Main");
        Console.ReadKey();
    }
}
  • 連續任務

如果一個任務的執行依賴于另一個任務,即任務的執行有先后順序,此時,我們可以使用連續任務,
task.ContinueWith(ReadNews)表示一個任務task結束后,才開始執行另一個任務,

class Program
{
    static void DownLoad(object str)
    {
        Console.WriteLine("DownLoad Begin ID = " + Thread.CurrentThread.ManagedThreadId + " " + str);
        Thread.Sleep(1000);
        Console.WriteLine("DownLoad End");
    }
    static void ReadNews(Task obj)
    {
        Thread.Sleep(1000);
        Console.WriteLine("Read News");
    }
    static void Main(string[] args)
    {
        Task task = new Task(DownLoad, "人民日報");
        Task task2 = task.ContinueWith(ReadNews);
        task.Start();
        Console.ReadKey();
    }
}
  • 任務的層次結構

在一個任務中可以啟動子任務,兩個任務異步執行,默認情況下,子任務(即由外部任務創建的內部任務)將獨立于其父任務執行,
使用TaskCreationOptions.AttachedToParent顯式指定將任務附加到任務層次結構中的某個父級,
如果父任務執行完了但是子任務沒有執行完,則父任務的狀態會被設定為WaitingForChildrenToComplete,只有子任務也執行完了,父任務的狀態才會變成RunToCompletion,

class Program
{
    static void DownLoad(object str)
    {
        Console.WriteLine("Parent Begin ID = " + Thread.CurrentThread.ManagedThreadId + " " + str);
 
        Task child = new Task(ChildWork, TaskCreationOptions.AttachedToParent);
        child.Start();
        Thread.Sleep(1000);
        Console.WriteLine("Parent End");
    }
 
    static void ChildWork()
    {
        Console.WriteLine("Child begin");
        Thread.Sleep(5000);
        Console.WriteLine("Child end");
    }
 
    static void Main(string[] args)
    {
        Task task = new Task(DownLoad, "人民日報");
        task.Start();
        Thread.Sleep(2000);
        Console.WriteLine(task.Status);
        Thread.Sleep(4000);
        Console.WriteLine(task.Status);
        Console.ReadKey();
    }
}
  • 任務的執行結果

使用Task的泛型版本,可以回傳任務的執行結果,
下面例子中的TaskWithResult的輸入為object型別,回傳一個元組Tuple<int, int>,
定義呼叫TaskWithResult的任務時,使用泛型類Task<Tuple<int, int>>,泛型的引數定義了回傳型別,通過建構式,傳遞TaskWithResult,建構式的第二個引數定義了TaskWithResult的輸入值,
任務完成后,通過Result屬性獲取任務的結果,

class Program
{
    static Tuple<int, int> TaskWithResult(object obj)
    {
        Tuple<int, int> div = (Tuple<int, int>)obj;
        Thread.Sleep(1000);
        return Tuple.Create<int, int>(div.Item1 + div.Item2, div.Item1 - div.Item2);
    }
    static void Main(string[] args)
    {
        var task = new Task<Tuple<int, int>>(TaskWithResult, Tuple.Create<int, int>(8, 3));            
        task.Start();
        Console.WriteLine(task.Result);
        task.Wait();
        Console.WriteLine("Result: {0} {1}", task.Result.Item1, task.Result.Item2);
        Console.ReadLine();
    }
}

9、死鎖的產生和避免

在這里插入圖片描述在這里插入圖片描述

10、異步委托

首先我們來看一個簡單的例子:

小明在燒水,等水燒開以后,將開水灌入熱水瓶,然后開始整理家務
小文在燒水,在燒水的程序中整理家務,等水燒開以后,放下手中的家務活,將開水灌入熱水瓶,然后繼續整理家務
這也是日常生活中很常見的情形,小文的辦事效率明顯要高于小明,從C#程式執行的角度考慮,小明使用的同步處理方式,而小文則使用的異步處理方式,
同步處理方式下,事務是按順序一件一件處理的;而異步方式則是,將子操作從主操作中分離出來,主操作繼續進行,子操作在完成處理的時候通知主操作,

【異步委托】
我們通過異步委托來完成:

class BoilWater
{
	static TimeSpan Boil()
	{
		Console.WriteLine("水壺:開始燒水...");
		Thread.Sleep(6000);
		Console.WriteLine("水壺:水已經燒開了!");
		return TimeSpan.MinValue;
	}
	delegate TimeSpan BoilingDelegate();
 
	static void Main(string[] args)
	{
		Console.WriteLine("小文:將水壺放在爐子上");
		BoilingDelegate d = new BoilingDelegate(Boil);
        IAsyncResult result = d.BeginInvoke(BoilingFinishedCallback, null);
		Console.WriteLine("小文:開始整理家務...");
        for (int i = 0; i < 20; i++)
        {
			Console.WriteLine("小文:整理第{0}項家務...", i + 1);
			Thread.Sleep(1000);
        }
	}
 
	static void BoilingFinishedCallback(IAsyncResult result)
	{
		AsyncResult asyncResult = (AsyncResult)result;
		BoilingDelegate del = (BoilingDelegate)asyncResult.AsyncDelegate;
        del.EndInvoke(result);
        Console.WriteLine("小文:將熱水灌到熱水瓶");
        Console.WriteLine("小文:繼續整理家務");
	}   
}

11、屏障Barrier

C# 并行編程 之 Barrier的使用 - 通過屏障同步并發任務

第七章 資料庫應用開發

1、 ADO.NET的主要特點

  • 不依賴于連續的活動連接
  • 使用資料命令執行資料庫互動
  • 使用資料集快取資料
  • 資料集獨立于資料源
  • 資料保持為XML
  • 通過架構定義資料結構

2、 ADO.NET物件模型的結構 DataAdapter、Command、DataReader、DataSet

在這里插入圖片描述
在這里插入圖片描述

3、 連接物件的創建

String connectStr = "server=自己的Server名稱;database=庫名;uid=資料庫賬號;pwd=資料庫密碼"; //SQL server身份驗證方法
SqlConnection connect = new SqlConnection(connectStr);

4、 執行資料命令的方法(ExecuteNonQuery、ExecuteReader、ExecuteScalar)

在這里插入圖片描述

5、 如何使用SqlCommand和SqlDataReader讀取SQL Server資料庫表,如何使用SqlCommand添加、洗掉和修改SQL Server資料庫表

String connStr = "server=自己的Server名稱;database=庫名;uid=資料庫賬號;pwd=資料庫密碼"; //SQL server身份驗證方法
SqlConnection conn = new SqlConnection(connStr);
//打開鏈接
conn.Open();

#region 查詢
//創建命令
MySqlCommand cmd = new MySqlCommand("select * from user ", conn);
//執行命令--讀取資料
MySqlDataReader  reader= cmd.ExecuteReader();
//讀取資料
while(reader.Read())//判斷是否有資料--//讀取一行記錄
{

    string username= reader.GetString("username");
    string password = reader.GetString("password");
    Console.WriteLine(username + ":" + password);
}
reader.Close();
#endregion


#region 插入資料            
string username = "cwer";
string password = "lcker"; 
//創建陳述句
MySqlCommand cmd = new MySqlCommand("insert into user set username='" + username + "'" + ",password='"+password+"'",conn);
//執行陳述句
cmd.ExecuteNonQuery();
conn.Close();
Console.ReadKey();//程式暫停
#endregion

6、 DataSet的主要屬性(Tables、Relations)

在這里插入圖片描述

7、 DataTable的主要屬性(Columns、Rows、PrimaryKey)

在這里插入圖片描述

8、 如何使用SqlDataAdapter物件把SQL Server資料庫表填充到DataSet的DataTable中,如何修改、添加、洗掉DataTable中的記錄并更新到資料庫中

使用SqlDataAdapter物件把SQL Server資料庫表填充到DataSet的DataTable中

SqlConnection thisConnection = new SqlConnection(connStr);
SqlDataAdapter thisAdapter = new SqlDataAdapter("SELECT * FROM student", thisConnection);
DataSet thisDataSet = new DataSet();	
thisAdapter.Fill(thisDataSet, "MyStudent");//Fill
foreach (DataRow theRow in thisDataSet.Tables["MyStudent"].Rows)
{
    Console.WriteLine(theRow["姓名"] + "\t" + theRow["年齡"]);
}
thisConnection.Close();

修改、添加、洗掉DataTable中的記錄并更新到資料庫中

SqlConnection thisConnection = new SqlConnection(connstr);
SqlDataAdapter thisAdapter = new SqlDataAdapter("SELECT * FROM student", thisConnection);
SqlCommandBuilder thisBuilder =  new SqlCommandBuilder(thisAdapter);//負責生成用于更新資料庫的SQL陳述句,不必自己創建這些陳述句
DataSet thisDataSet = new DataSet();
thisAdapter.Fill(thisDataSet, "Stu");
//修改
thisDataSet.Tables["Stu"].Rows[0]["年齡"] = 18;
thisAdapter.Update(thisDataSet, "Stu");//遍歷DataTable中的行,找出需要對資料庫作出的變動
//添加
DataRow thisRow = thisDataSet.Tables["Stu"].NewRow();
thisRow["姓名"] = "張華";
thisRow["年齡"] = 21;
thisDataSet.Tables["Stu"].Rows.Add(thisRow);
thisAdapter.Update(thisDataSet, "Stu");
//洗掉
DataColumn[] keys = new DataColumn[1];
keys[0] = thisDataSet.Tables["Stu"].Columns["姓名"];
thisDataSet.Tables["Stu"].PrimaryKey = keys;
DataRow findRow = thisDataSet.Tables["Stu"].Rows.Find("張華");
if (findRow != null) {
     Console.WriteLine("張華 already in Customers table");
     Console.WriteLine("Removing 張華  . . .");
     findRow.Delete();
     thisAdapter.Update(thisDataSet, "Stu");
}

10、如何使用SqlCommand執行帶輸出引數的存盤程序

create  procedure  RegionSelect  as
   set  nocount  off
   select * from Region
Go

private  static  SqlCommand  GenerateSelectCommand(SqlConnection   conn)
{
    SqlCommand  aCommand=new SqlCommand(“RegionSelect”,conn);
    aCommand.CommandType=CommandTye.StoredProcedure;
    aCommand.UpdatedRowSource=UpdateRowSource.None;
    return  aCommand;
 }
DataSet   ds=new   DataSet();
SqlDataAdapter  da=new  SqlDataAdapter();
da.SelectCommand=GenerateSelectCommand(conn);
da.Fill(ds,”Region”);

11、DataRowState和AcceptChanges、Update方法

DataRow類的RowState屬性
DataRowState.Added 已添加
DataRowState.Deleted 已洗掉
DataRowState.Detached 已創建
DataRowState.Modified 已修改
DataRowState.Unchanged 未更改

一般在成功更新資料源之后呼叫AcceptChanges()方法

呼叫DataAdapter物件的Update( )方法,把這個變化回傳到資料庫中
thisAdapter.Update(thisDataSet, “Stu”);

12、在ADO.NET中訪問多個表 見課堂示例程式TableRelation

沒講

13、DataColumnVersion

在這里插入圖片描述

14、UpdatedRowSource的含義和示例

在這里插入圖片描述

Both
存盤程序可以回傳輸出引數和一個完整的資料庫記錄,這兩個資料源都用于更新源資料行
FirstReturnedRecord
該命令回傳一個記錄,該記錄的內容應合并到最初的源DataRow中,當給定的表有許多默認(或計算)列時,使用這個值很有用,因為在執行insert陳述句之后,這些行需要與客戶端上的DataRow同步,
None
丟棄從該命令回傳的所有資料
OutputParameters
命令的任何輸出引數都映射到DataRow的對應列上

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace UpdatedRowSourceDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            string ss = "Data Source=.\\MYSQLSERVER;Initial Catalog=MyDB;Integrated Security=True";
            SqlConnection con = new SqlConnection(ss);
            con.Open();
            SqlDataAdapter sda = new SqlDataAdapter();
            sda.SelectCommand =new SqlCommand( "select * from Student",con);
            SqlCommand cmd = new SqlCommand("ReturnValue5", con);
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add(new SqlParameter("rv", SqlDbType.Int, 10, ParameterDirection.Output, false, 10, 0, "年齡", DataRowVersion.Default, null));
            cmd.UpdatedRowSource = UpdateRowSource.Both;
            DataSet ds = new DataSet();
            sda.Fill(ds, "stu");
            sda.InsertCommand = cmd;
            DataRow dr = ds.Tables["stu"].NewRow();
            dr[0] = "蔣曉欣";
            dr[1] = 22;
            dr[2] = "女";
            dr[3] = "本科生";
            ds.Tables["stu"].Rows.Add(dr);
            sda.Update(ds, "stu");
         /*   sda.UpdateCommand = cmd;   */         
            DataTable dt = ds.Tables["stu"];
         /*   dt.Rows[0][1] = 40;
            sda.Update(ds, "stu");*/
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                for (int j = 0; j < dt.Columns.Count; j++)
                    Console.Write(dt.Rows[i][j] + "  ");
                Console.WriteLine();
            } 
            con.Close();
        }
    }
}

第八章 泛型

1、.net 泛型與C++模板的不同

在這里插入圖片描述

2、泛型在性能、型別安全、二進制代碼的重用、代碼的擴展方面的表現

  • 性能
    不再進行裝箱和拆箱操作
  • 型別安全
    添加的型別得相同
  • 二進制代碼的重用
    泛型類可以定義一次,并且可以用許多不同的型別實體化,而不需要像C++模板那樣訪問源代碼
  • 代碼的擴展

3、泛型型別的命名約定

在這里插入圖片描述

public class List { }
public class LinkedList { }

4、創建泛型類

public class LinkedListNode<T>
{
	public LinkedListNode(T value)
	{
		this.Value = value;
	}
   
	public T Value { get; private set; }
	public LinkedListNode<T> Next { get; internal set; }
	public LinkedListNode<T> Prev { get; internal set; }
}

5、泛型類的功能

在這里插入圖片描述

using System;
using System.Collections.Generic;
namespace Wrox.ProCSharp.Generics
{
    public class DocumentManager<T>        
    {
        private readonly Queue<T> documentQueue = new Queue<T>();
        public void AddDocument(T doc)
        {
            lock (this)
            {
                documentQueue.Enqueue(doc);
            }
        }
        public bool IsDocumentAvailable
        {
            get { return documentQueue.Count > 0; }
        }

6、泛型型別使用時需注意的地方

不能假定類提供了什么型別

Class  MyGenericClass<T1,T2,T3>
{
     private  T1  innerT1Object;
     public  MyGenericClass(T1  item)
     {  innerT1Object=new  T1();  }//編譯錯誤
     public   T1  InnerT1Object
     {    
           get
           {   return  innerT1Object; }
      }
}

我們不知道T1是什么,也就不能使用它的建構式,它甚至
可能沒有建構式,或者沒有可公共訪問的默認建構式

當比較為泛型型別提供的型別值和null時,不能使用運算子==和!=

public  bool  Compare(T1  op1, T1  op2)
{
    if  (op1 != null && op2 != null)
           return  true;
   else
           return  false;
}

其中,如果T1是一個值型別,則總是假定它是非空的,于是,
在上面的代碼中,Compare總是回傳true,

7、默認值

在這里插入圖片描述

8、約束

class  MyGenericClass<T1,T2>: MyBaseClass, IMyInterface
where T1:constraint1  where  T2: constraint2
{
     ……
}

在這里插入圖片描述

只能為默認建構式定義建構式約束,不能為其他建構式定義建構式約束
使用泛型型別還可以合并多個約束

public  class  MyClass<T> where T: IFoo, new()
{
    ……
}
//如果使用new()作約束,它就必須是為型別指定的最后一個約束
class  MyGenericClass<T1,T2> where  T2: T1
{
     ……
}
//其中,T2必須與T1型別相同,或者繼承自T1,這稱為裸型別約束,
//表示一個泛型型別引數用作另一個型別引數的約束

9、繼承

泛型型別可以實作泛型介面,也可以派生自一個類
泛型類可以派生自泛型基類

public  class  LinkedList<T> : IEnumerable<out T>
{
    ……
}

public  class  Base<T>{……}
public  class  Derived<T>: Base<T>{……}

10、靜態成員

泛型類的靜態成員只能在類的一個實體中共享

public    class   StaticDemo<T>
{
    public  static  int  x;
}

StaticDemo<string>.x=4;
StaticDemo<int>.x=5;
Console.WriteLine(StaticDemo<string>.x); //輸出4

11、泛型運算子

//隱式轉換
public static implicit operator List<Animal>(Farm<T> farm)
{
    List<Animal> result = new List<Animal>();
    foreach (T animal in farm)
    {
        result.Add(animal);
    }
    return result;
}

//多載+
public static Farm<T> operator+(Farm<T> farm1, List<T> farm2)
{
    Farm<T> result = new Farm<T>();
    foreach (T animal in farm1)
    result.Animals.Add(animal);
    foreach (T animal in farm2)
    {
        if (!result.Animals.Contains(animal))
            result.Animals.Add(animal);
    }
    return result;
}
public static Farm<T> operator +(List<T> farm1, Farm<T> farm2)
{
    return farm2 + farm1;
}

12、泛型介面的協變與抗變

在這里插入圖片描述

public interface IIndex<out T>
{
    T this [int index] { get; }
    int Count { get; }         
}
IIndex<Rectangle> r=new RectangleCollection();
IIndex<Shape> s=r;

在這里插入圖片描述

public interface IDisplay<in T>
{
    void Show(T item);
}

13、可空型別

Nullable<int> x;//1
int? x2;//2

14、泛型方法

void  Swap<T>(ref  T  x,  ref  T  y)
{
    T  temp;
    temp=x;
    x=y;
    y=temp;
}
int   i=4, j=5;
Swap<int>(ref  i, ref  j);

如果類是泛型的,就必須為泛型方法型別使用不同的識別符號

15、泛型方法的規范

泛型方法可以多載,為特定的型別定義規范

public class MethodOverloads  {
    public void Foo<T>(T obj)   {
        Console.WriteLine("Foo<T>(T obj), obj type: {0}", obj.GetType().Name);
    }
    public void Foo(int x)  {
        Console.WriteLine("Foo(int x)");
    }
    public void Bar<T>(T obj)  {
        Foo(obj);
}
  • 在編譯期間,會使用最佳匹配,如果傳遞了一個int,就選擇帶int引數的方法;對于其他引數型別,編譯器會選擇方法的泛型版本

  • 所呼叫的方法是在編譯期間定義的,而不是運行期間

  • Bar()方法選擇了泛型Foo()方法,而不是用int引數多載的Foo()方法,原因是編譯器在編譯期間選擇Bar()方法呼叫的Foo()方法,由于Bar()方法定義了一個泛型引數,而且泛型Foo()方法匹配這個型別,所以呼叫了Foo()方法,在運行期間給Bar()傳遞一個int值不會改變這一點

第九章 C#語言的改進

1、自動屬性

 public int MyProp{ get; set; }
  • 使用自動屬性時,只能通過屬性訪問資料,不能通過底層的私有欄位訪問,因為我們不知道底層私有欄位的名稱
  • 自動屬性必須包含get和set訪問塊,無法使用這種方式定義只讀或只寫屬性

2、物件初始化器

<className>  <variableName>=new <className>
{
     <propertyOrField1>=<value1>,
     <propertyOrField2>=<value2>,
     ……
     <propertyOrFieldN>=<valueN>
 }

集合初始化器
在這里插入圖片描述

3、型別推理

var varName = value;

  • 變數varName隱式地型別化為value的型別
  • 如果編譯器不能確定var宣告的變數型別,代碼就不會編譯,因此,在用var宣告變數時,必須同時初始化該變數,因為如果沒有初始值,編譯器就不能確定變數的型別
    在這里插入圖片描述
    var myArray=new[] {3,”not an int”,5};

4、Lambda運算式與匿名方法

匿名方法
匿名方法純粹是為了委托目的而創建
delegate (parameters)
{
……
};

在這里插入圖片描述

Lambda運算式的引數
隱式引數:(a,b)=>a+b
顯式引數:(int a,int b)=>a+b

PerformOperations((a,b)=>a+b); 可改寫為

PerformOperations(delegate(int a,int b)
{
	return a+b;
});

PerformOperations((a,b)=>
{
	return a+b;
}); 

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/393987.html

標籤:其他

上一篇:元旦將至,Html動態特效祝福送給你

下一篇:【歷史上的今天】12 月 26 日:現代計算機鼻祖誕生;手機之父出生;美國史上最大資訊盜竊案

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more