2017.07.24-2017.07.30
關於組件(Component)、控件(Control)和用戶控件(UserControl)
在.NET中有組件、控件和用戶控件。其實從字面上已經可以理解各自的不同了。但是具體關係其實是從類的繼承上來區別的。一般控件派生於:Control類,所以從此類派生出的稱之爲控件。一般組件派生於:Component類,所以從此類派生出的稱之爲組件。一般用戶控件派生於:UserControl類,所以從該類派生出的稱之爲用戶控件。(我們之所以這麼叫其實是因爲英文翻譯上的習慣)他們之間的關係主要是:UserControl繼承Control繼承Component。
但是具體在用時有什麼區別呢?這主要是從設計的角度去考慮的。
組件和一般類的區別:我們總是習慣於面向對象的設計方式。而對象則是由類實例化而來。我們強調萬事萬物皆對象,把對象看作設計的基本單元。
所謂組件其實是面向組件的設計方式,我們把組件作爲設計的基本單元。組件即爲程序的組成部分。其實是構成程序的一個最基本的單元。一個組件其實可以包括多個類。這與傳統的面向對象的設計方式有點區別。算是更高一層的封裝。
而控件和用戶控件其實是組件按照具體的用途的一種劃分,它們都是組件。控件的突出特點就是交互式組件。而用戶控件則是將某些特定的組件或控件複合從而實現特定的業務功能。所以用戶控件往往是從業務角度來設計的。
其實,程序設計現在已經不在是簡單的面向對象。
從以往的面向過程到
面向對象
面向組件
面向服務
面向方向
其實有很多。
菜單的動態生成及事件綁定(會用到類型強轉)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MenuDynamic
{
public partial class Form1 : Form
{
ToolStripMenuItem[] toolStripMenuItem = new ToolStripMenuItem[5];
public Form1()
{
InitializeComponent();
for (int i = 0; i < toolStripMenuItem.Length; i++)
{
toolStripMenuItem[i] = new ToolStripMenuItem();
toolStripMenuItem[i].Name = "Series" + i;
toolStripMenuItem[i].Tag = "Series";
toolStripMenuItem[i].Checked = true;
contextMenuStrip1.Items.Add(toolStripMenuItem[i].Name);
toolStripMenuItem[i].Text = toolStripMenuItem[i].Name;
//contextMenuStrip1.Items[toolStripMenuItem[i].Name].Checked = true;
//綁定事件,兩次
contextMenuStrip1.Items[toolStripMenuItem.Length - 2 + i].Click += toolStripMenuItem_Click;
//toolStripMenuItem4.Click += toolStripMenuItem_Click;
}
//toolStripMenuItem2.Checked = true;
//下面這句話是不起作用的,需要用類型強轉獲取當前選中的item,強轉中,有時會發生自己轉成自己的情況
toolStripMenuItem[1].Checked = true;
//這裏能用foreach是因爲不會在其中發生remove和add,如果有,就會報錯,出現異常
foreach (var item in contextMenuStrip1.Items)
{
if (item is ToolStripMenuItem)
{
ToolStripMenuItem menuItem = item as ToolStripMenuItem;
menuItem.Checked = true;
}
}
}
//toolStripMenuItem的點擊事件,check屬性要在這裏設置,注意類型強轉
private void toolStripMenuItem_Click(object sender, EventArgs e)
{
((ToolStripMenuItem) sender).Checked = !((ToolStripMenuItem) sender).Checked;
label1.Text = sender.ToString();
}
}
}
數組和集合的對比
集合提供了程序中管理數據的各種辦法,它們能夠取代數組靈活地管理對象組。
數組和集合之間的差別在於:
- 數組聲明瞭元素類型,集合卻沒有。這是因爲集合類將元素存儲爲對象
- 數組實例的大小是固定的,而集合類可以按照需要動態調整自身大小
- 數組是可讀寫的數據結構,無法創建一個只讀數組。但是通過使用只讀ReadOnly方法,就可以以只讀方式使用集合類。當以只讀方式使用集合類時,任何試圖寫入的操作都將引起運行時異常。
封裝
是一種信息隱蔽技術,用戶只能看到對象封裝界面上的信息,對象內部對用戶是隱藏的。目的在於把設計者和使用者分開。
Dictionary類
在C#中,Dictionary提供快速的基於鍵值的元素查找。當你有很多元素的時候可以使用它。它包含在System.Collections.Generic名空間中。在使用前必須聲明它的鍵類型和值類型。
using System;
using System.Collections.Generic;
public class Example
{
public static void Main()
{
// Create a new dictionary of strings, with string keys.
//第一個string是Key,第二個String是Value
Dictionary<string, string> openWith =
new Dictionary<string, string>();
// Add some elements to the dictionary. There are no
// duplicate keys, but some of the values are duplicates.
//往dictionary中添加元素,Key不能包含重複值,Value可以包含重複值
//比如可以把對象作爲值,對象中某個不可重複的元素作爲鍵,即可做到快速的增刪改查操作
openWith.Add("txt", "notepad.exe");
openWith.Add("bmp", "paint.exe");
openWith.Add("dib", "paint.exe");
openWith.Add("rtf", "wordpad.exe");
// The Add method throws an exception if the new key is
// already in the dictionary.
//若字典中已經包含某個key了,則Add方法會拋出異常
try
{
openWith.Add("txt", "winword.exe");
}
catch (ArgumentException)
{
Console.WriteLine("An element with Key = \"txt\" already exists.");
}
//可通過鍵來找到對應的值
// The Item property is another name for the indexer, so you
// can omit its name when accessing elements.
Console.WriteLine("For key = \"rtf\", value = {0}.",
openWith["rtf"]);
// The indexer can be used to change the value associated
// with a key.
//改
openWith["rtf"] = "winword.exe";
Console.WriteLine("For key = \"rtf\", value = {0}.",
openWith["rtf"]);
// If a key does not exist, setting the indexer for that key
// adds a new key/value pair.
openWith["doc"] = "winword.exe";
// The indexer throws an exception if the requested key is
// not in the dictionary.
//若不在字典中則會拋異常
try
{
Console.WriteLine("For key = \"tif\", value = {0}.",
openWith["tif"]);
}
catch (KeyNotFoundException)
{
Console.WriteLine("Key = \"tif\" is not found.");
}
// When a program often has to try keys that turn out not to
// be in the dictionary, TryGetValue can be a more efficient
// way to retrieve values.
//可以用此函數實現獲取字典中某個鍵的值
string value = "";
if (openWith.TryGetValue("tif", out value))
{
Console.WriteLine("For key = \"tif\", value = {0}.", value);
}
else
{
Console.WriteLine("Key = \"tif\" is not found.");
}
// ContainsKey can be used to test keys before inserting
// them.
//ContainsKey可以在插入元素之前檢測
if (!openWith.ContainsKey("ht"))
{
openWith.Add("ht", "hypertrm.exe");
Console.WriteLine("Value added for key = \"ht\": {0}",
openWith["ht"]);
}
// When you use foreach to enumerate dictionary elements,
// the elements are retrieved as KeyValuePair objects.
//遍歷
Console.WriteLine();
foreach( KeyValuePair<string, string> kvp in openWith )
{
Console.WriteLine("Key = {0}, Value = {1}",
kvp.Key, kvp.Value);
}
// To get the values alone, use the Values property.
Dictionary<string, string>.ValueCollection valueColl =
openWith.Values;
// The elements of the ValueCollection are strongly typed
// with the type that was specified for dictionary values.
Console.WriteLine();
foreach( string s in valueColl )
{
Console.WriteLine("Value = {0}", s);
}
// To get the keys alone, use the Keys property.
Dictionary<string, string>.KeyCollection keyColl =
openWith.Keys;
// The elements of the KeyCollection are strongly typed
// with the type that was specified for dictionary keys.
Console.WriteLine();
foreach( string s in keyColl )
{
Console.WriteLine("Key = {0}", s);
}
// Use the Remove method to remove a key/value pair.
Console.WriteLine("\nRemove(\"doc\")");
openWith.Remove("doc");
if (!openWith.ContainsKey("doc"))
{
Console.WriteLine("Key \"doc\" is not found.");
}
}
}
/* This code example produces the following output:
An element with Key = "txt" already exists.
For key = "rtf", value = wordpad.exe.
For key = "rtf", value = winword.exe.
Key = "tif" is not found.
Key = "tif" is not found.
Value added for key = "ht": hypertrm.exe
Key = txt, Value = notepad.exe
Key = bmp, Value = paint.exe
Key = dib, Value = paint.exe
Key = rtf, Value = winword.exe
Key = doc, Value = winword.exe
Key = ht, Value = hypertrm.exe
Value = notepad.exe
Value = paint.exe
Value = paint.exe
Value = winword.exe
Value = winword.exe
Value = hypertrm.exe
Key = txt
Key = bmp
Key = dib
Key = rtf
Key = doc
Key = ht
Remove("doc")
Key "doc" is not found.
*/
//降序字典排序
//Dictionary<string, StudentInformationClass>爲字典的鍵值對
public static Dictionary<string, StudentInformationClass> SortDictionary_Desc(Dictionary<string, StudentInformationClass> dic)
{
List<KeyValuePair<string, StudentInformationClass>> myList = new List<KeyValuePair<string, StudentInformationClass>>(dic);
myList.Sort(delegate (KeyValuePair<string, StudentInformationClass> s1, KeyValuePair<string, StudentInformationClass> s2)
{
return s2.Value.GradeStudent.CompareTo(s1.Value.GradeStudent);
});
dic.Clear();
foreach (KeyValuePair<string, StudentInformationClass> pair in myList)
{
dic.Add(pair.Key, pair.Value);
}
return dic;
}
//升序字典排序
//Dictionary<string, StudentInformationClass>爲字典的鍵值對
public static Dictionary<string, StudentInformationClass> SortDictionary_Asc(Dictionary<string, StudentInformationClass> dic)
{
List<KeyValuePair<string, StudentInformationClass>> myList = new List<KeyValuePair<string, StudentInformationClass>>(dic);
myList.Sort(delegate (KeyValuePair<string, StudentInformationClass> s1, KeyValuePair<string, StudentInformationClass> s2)
{
return s1.Value.GradeStudent.CompareTo(s2.Value.GradeStudent);
});
dic.Clear();
foreach (KeyValuePair<string, StudentInformationClass> pair in myList)
{
dic.Add(pair.Key, pair.Value);
}
return dic;
}
CsvHelper組件使用中遇到的問題
【中文亂碼】——StreamReader sr = new StreamReader(fileStream, Encoding.GetEncoding("GB2312"));
StreamReader
類用於讀取文件,可以處理任何流信息,它以一種特定的編碼從字節流中讀取字符。
using關鍵字有兩個主要用途
using
關鍵字有兩個主要用途:
- 作爲指令:用於爲命名空間創建別名或導入在其他命名空間中定義的類型。
- 作爲語句:用於定義一個範圍,在此範圍的末尾將釋放對象。
非託管資源和託管資源
託管資源指的是.NET
可以自動進行回收的資源,主要是指託管堆上分配的內存資源。託管資源的回收工作是不需要人工干預的,有.NET
運行庫在合適調用垃圾回收器進行回收。
非託管資源指的是.NET
不知道如何回收的資源,最常見的一類非託管資源是包裝操作系統資源的對象,例如文件,窗口,網絡連接,數據庫連接,畫刷,圖標等。這類資源,垃圾回收器在清理的時候會調用Object.Finalize()
方法。默認情況下,方法是空的,對於非託管對象,需要在此方法中編寫回收非託管資源的代碼,以便垃圾回收器正確回收資源。
委託再探
Control.Invoke
方法 (Delegate
)
在擁有此控件的基礎窗口句柄的線程上執行指定的委託。即調用此方法可以將權限轉交給擁有此控件的基礎窗口句柄的線程。(比如,可以是反交給主線程,讓主線程幫忙做)
類和線程無關。
另一種實現委託的方法,將當前窗體作爲對象傳給線程。這個實例中會產生包括主線程在內的三個線程。
//MyFormControl.cs
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace DelegateApp
{
public partial class MyFormControl : Form
{
public delegate void AddListItem();
public AddListItem myDelegate;
private Button myButton;
private Thread myThread;
private ListBox myListBox;
public MyFormControl()
{
//窗體初始化
myButton = new Button();
myListBox = new ListBox();
myButton.Location = new Point(72, 160);
myButton.Size = new Size(152, 32);
myButton.TabIndex = 1;
myButton.Text = "Add items in list box";
myButton.Click += new EventHandler(Button_Click);
myListBox.Location = new Point(48, 32);
myListBox.Name = "myListBox";
myListBox.Size = new Size(200, 95);
myListBox.TabIndex = 2;
ClientSize = new Size(292, 273);
Controls.AddRange(new Control[] { myListBox, myButton });
Text = " 'Control_Invoke' example";
myDelegate = new AddListItem(AddListItemMethod);
}
static void Main()
{
//新線程展示窗體
MyFormControl myForm = new MyFormControl();
myForm.ShowDialog();
}
//委託函數
public void AddListItemMethod()
{
String myItem;
for(int i=1;i<11;i++)
{
myItem = "MyListItem" + i.ToString();
myListBox.Items.Add(myItem);
myListBox.Update();
Thread.Sleep(300);
}
}
private void Button_Click(object sender, EventArgs e)
{
//再起一個線程
myThread = new Thread(new ThreadStart(ThreadFunction));
myThread.Start();
}
private void ThreadFunction()
{
//把當前窗體作爲對象傳進去,生成MyThreadClass的對象
MyThreadClass myThreadClassObject = new MyThreadClass(this);
//利用函數調用委託
myThreadClassObject.Run();
}
}
}
//MyThreadClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WindowsFormsApp4
{
public class MyThreadClass
{
MyFormControl myFormControl1;
public MyThreadClass(MyFormControl myForm)
{
myFormControl1 = myForm;
}
public void Run()
{
// Execute the specified delegate on the thread that owns
// 'myFormControl1' control's underlying window handle.
//將權限轉交給擁有此控件的基礎窗口句柄的線程,執行委託
myFormControl1.Invoke(myFormControl1.myDelegate);
}
}
}
接口
- 接口即規範。接口中所聲明的成員都是公共的;
- 接口不能包含有具體實現代碼的成員,也不能包含構造函數;
定義接口
在默認情況下,接口和類一樣,將聲明爲內部訪問(internal),即只能在同一程序集中訪問,因此如果要讓接口對外公開,應當加上public
修飾符。
接口與多繼承
在C++語言中允許多繼承,但是C#不行。C#一個類可以實現多個接口,在形式上達到了多繼承的效果。
實現接口
=============================================================================
拷貝構造函數
與有些語言不同,C# 不提供複製構造函數。如果創建了新的對象並希望從現有對象複製值,必須自行編寫適當的方法。(MSDN文檔)
用途
構造函數是用來初始化我們要創建實例的特殊的方法。通常我們要將一個實例賦值給另外一個變量c#只是將引用賦值給了新的變量實質上是對同一個變量的引用,如果想在賦值的同時創建一個全新的變量而不只是對實例引用的賦值,我們可以使用複製構造函數。
數組
一維數組
int[] nums = new int [3];
二維數組
聲明
int[,] arr;
ys爲二維數組
int row = ys.GetLength(0);//獲取行數
int col = ys.GetLength(1);//獲取列數
取二維數組的某一行:
//ys爲二維數組
for (int i = 0; i < row; i++)
{
//獲取一行數據到tmp中
for (int j = 0; j < col; j++)
{
tmp[j] = ys[i, j];
}
}
switch條件語句
switch語句是分支選擇語句,switch中的表達式是一個整型或字符串型表達式,case的內容根據switch而定
//比如
Console.write("請輸入國家名稱:");
string country = Console.ReadLine();
string language;
switch(country)
{
case "America":
case "Britain":
language = "English";
break;
default :
language = "unknown"
break;
}
Console.WriteLine(language);
===================================
Matlab的MAT格式
文件中開頭一部分是:MATLAB 5.0 MAT-file, Platform: PCWIN64, Created on: Tue Jul 25 14:37:21 2017
類似的字樣。