CLR是一个可以由多编程语言使用的运行时。
CLR的核心功能:内存管理,程序集加载,安全性,异常处理,线程同步等等。可以被很多属于微软系列的开发语言使用。
特点:跨平台、跨语言、跨标准
优势:适用于windows平台
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
System.Array是所有数组类型的抽象基类型,所有的数组类型均由它派生,任何数组都可以使用System.Array具有的属性及方法
//声明
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 };
//声明
数组元素类型[,] 数组名; 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’};
一维数组:数组名.Length 是数组元素的个数
二维数组:
数组名.Length 是规则二维数组含有的总元素的个数
int[,] c = new int[3, 4]; //c.Length为12
数组名.Length 是锯齿状二维数组含有的一维数组的个数
int[][] c = new int[3][]; //c.Length为3
//foreach (类型 标识符 in 集合表达式)
//语句;
int[] ints = { 1, 2, 3 };
foreach (int temp in ints)
Console.WriteLine(temp);
ArrayList arr = new ArrayList();
string str1;
str1 = Console.ReadLine();
arr.Add(str1);
//定义属性结构
public int MyIntProp{
get{
//get code
}
set{
//set cod
}
}
//只读
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;}
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;
}
}
}
- 集合
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);
}
}
}
}
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); }
}
//多个参数索引器
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));
}
}
- 委托的定义
委托是函数的封装,它代表一类函数,它们都符合一定的签名:拥有相同的参数列表和返回值类型。
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());
}
}
//调用实例方法
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);
//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();
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();
}
}
[构造函数修饰符] 标识符([参数列表] )
[ : 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();
}
}
}
//二元操作符“+”重载
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);
}
//隐式类型转换,实现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;
}
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);
常用属性
Text
按钮上显示的文本包含在Text属性中。如果文本超
出按钮宽度,则换到下一行。可以包含访问键。
FlatStyle
如果把按钮样式设置为Popup,则按钮就显示为平
面,直到用户把鼠标指针移动到它上面为止。此
时,按钮会弹出,显示为正常的3D外观。
Enabled
设置为false,按钮会灰显,单击它不起任何作用
Image
可以指定在一个按钮上显示的图像(位图,图标等)
ImageAlign
设置按钮的图像在什么地方设置
ImageList
AcceptButton
在任何Windows窗体上都可以指定某个Button控件为接受按钮。每当用户按Enter键时,即单击默认按钮,而不管当前窗体上其他哪个控件具有焦点
CancelButton
每当用户按ESC键时,即单击取消按钮,而不管当前窗体上其他哪个控件具有焦点
HelpButton
获取或设置一个值,该值指示是否应在窗体的标题框中显示“帮助”按钮。
常用事件
Click
该控件不支持双击事件
常用属性
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控件的属性
Appearance
如果将该属性设置为Appearance.Button,则RadioButton的外观可以像命令按钮一样
AutoCheck
该属性设置为true, 用户单击单选按钮时,自动被选中或取消选中。否则,必须在Click事件处理程序中手工设置Checked属性
Checked
表示控件是否被选中的标记
CheckAlign
可以改变单选按钮的对齐形式,默认是
ContentAlignment.MiddleLeft
RadioButton控件的事件
CheckedChanged
当RadioButton的选中状态改变时,引发该事件
Click
每次单击RadioButton时引发该事件。连续单击RadioButton两次或多次只改变checked属性一次。如果被单击按钮的AutoCheck属性是false,则该按钮根本不会被选中,只引发click事件
CheckBox控件的属性
CheckState
与RadioButton不同,CheckBox有三种状态:Checked、Indeterminate、Unchecked。复选框的状态是Indeterminate时,表示复选框的当前值是无效的或者在当前环境下没有意义
ThreeState
当属性为false时,用户不能把CheckState属性改为Indeterminate
CheckBox控件的事件
CheckedChanged
当复选框的Checked属性改变时,就引发该事件。注意在复选框中,当ThreeState属性为true时,单击复选框不会改变Checked属性。在复选框由Checked变为indeterminate状态时,就会出现这种情况
CheckStateChanged
当CheckState属性改变时,引发该事件
常用属性
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
在选中文本发生变化时,引发该事件。
常用属性
SelectedIndex
表示选中选项的基于0的索引,若选中多项,则是第一项的索引
ColumnWidth
在包含多个列的列表框中指定列的宽度
Items
包含列表框中的所有选项
MultiColumn
获取和设置列表框中列的数目
SelectedIndices
列表框中选中的多项基于0的索引集合
SelectedItem
指选中的选项。若 选中多项,则指第一项
SelectedItems
包含当前选中的所有选项
Sorted
该属性设置为true,可使列表框对它所包含的选项按照字母顺序排序
Text
设置该属性,将搜索匹配该文本的选项,并选择该选项;获取该属性,返回的值是列表中第一个选中的选项
SelectionMode
可以使用ListSelectionMode枚举中的4种选择模式
None 不能选择任何选项
One 一次只能选择一个选项
MultiSimple 可选择多个选项
MultiExtended 可选择多个选项,用户可使用Ctrl、Shift、和箭头键进行选择。
常用方法
public void BeginUpdate ()
当将多项一次一项地添加到 ComboBox 时维持性能。
public void EndUpdate ()
在 BeginUpdate 方法挂起绘制后,该方法恢复绘制 ComboBox 控件。
…
常用属性
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
激活一个选项时,引发该事件
用于显示位图(.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事件
InitialDirectory属性
文件对话框显示的初始目录
默认情况下,对话框将打开用户在上一次运行应用
程序时打开的目录
默认值是一个空串,表示用户的“我的文档”目录
Filter属性
设置文件过滤器,定义用户可以选择打开的文件类型
每个部分需要有两个字符串,第一个字符串定义要在文本框中显示的文本,第二个字符串用于指定要在对话框中显示的文件扩展名
FilterIndex属性
指定列表框中的默认选项。 基于1
ValidateNames属性
检查用户输入的文件名,看其是否是一个有效的文件名。
该属性设置为true,可以使用CheckFileExists属性验证
文件的有效性,使用CheckPathExists属性验证路径的有效性
FileName属性
包含在文件对话框中选定文件名的字符串
Multiselect属性
该属性设置为true,用户可以选中多个文件
FileNames属性
包含所有选中文件名的字符串。包含的文件顺序与
选中它们的顺序相反。
OpenFileDialog的专用属性
ShowReadOnly属性
指示对话框是否包含只读复选框
ReadOnlyChecked属性
指示是否选定只读复选框
OpenFileDialog的常用方法
public Stream OpenFile ()
打开用户选定的具有只读权限的文件
常用属性
AddExtension
指示如果用户省略扩展名,对话框是否自动在文件名中添加扩展名。
DefaultExt
设置文件默认扩展名
CreatePrompt
指示如果用户指定不存在的文件,对话框是否提示用户允许创建该文件
OverwritePrompt
指示如果用户指定的文件名已存在,Save As 对话框是否显示警告。
常用属性
AllowVectorFonts
指示是否可在字体列表中选择矢量字体,默认为true
AllowVerticalFonts
指示是否可在字体列表中选择垂直字体,默认为true
FixedPitchOnly
该属性设置为true,仅在字体列表中显示固定大小的字体,默认为false
MaxSize
定义用户可以选择的最大字号
MinSize
定义用户可以选择的最小字号
ShowApply
该属性设置为true,显示Apply按钮
ShowEffects
该属性设置为true,可以选择Strikeout和Underline复选框来处理字体
ShowColor
该属性设置为true,在对话框中显示Color选项
AllowScriptChange
该属性设置为false,可防止用户改变字体的脚本
FontMustExist
指示对话框是否指定当用户试图选择不存在的字体或样式时的错误条件
Apply事件
单击Apply按钮触发的事件
…
不想掌握
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);
}
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);
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();
}
public StreamReader (Stream stream)
public StreamReader (string path)
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()
//从流的当前位置到末尾读取流
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)
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();
启用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) { }
//public Thread (ThreadStart start)指定入口
Thread compressThread = new Thread(entryPoint);
static void DoCompress(){
//代码
}
ThreadStart entryPoint = new ThreadStart(DoCompress);
//启动线程,即给线程分配除处理器之外的系统资源并执行各种安全性检查。
compressThread.Start();//在调用该方法后,新线程并不是处于Running状态,而是处于Unstarted状态
compressThread.Suspend();//使线程处于阻塞状态
compressThread.Resume();//恢复被挂起的线程,进入就绪状态
compressThread.Abort();//中止线程,永久删除不能重新启动
compressThread.Join();//进入阻塞,等待调用该方法线程执行完毕
compressThread.Sleep(int millisecondsTimeout);//睡会儿,睡醒就绪
CurrentThread
获取当前正在运行的线程
Thread myOwnThread = Thread.CurrentThread;
Name
线程的名称
Priority
指示线程的调度优先级
从高到低为:(同级时间片轮转)
ThreadPriority.Highest
ThreadPriority.AboveNormal
ThreadPriority.Normal
ThreadPriority.BelowNormal
ThreadPriority.Lowest
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();
public static void myStaticThreadMethod()
{
Thread.Sleep(3000);
}
Thread thread = new Thread(myStaticThreadMethod);
// thread.IsBackground = true;
thread.Start();
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);
}
}
}
}
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 )
//通知所有的等待线程对象状态的更改
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);
}
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);
}
}
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();
}
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();
}
}
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。
定义调用TaskWithResult的任务时,使用泛型类Task>,泛型的参数定义了返回类型。通过构造函数,传递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();
}
}
首先我们来看一个简单的例子:
小明在烧水,等水烧开以后,将开水灌入热水瓶,然后开始整理家务
小文在烧水,在烧水的过程中整理家务,等水烧开以后,放下手中的家务活,将开水灌入热水瓶,然后继续整理家务
这也是日常生活中很常见的情形,小文的办事效率明显要高于小明。从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("小文:继续整理家务");
}
}
C# 并行编程 之 Barrier的使用 - 通过屏障同步并发任务
String connectStr = "server=自己的Server名称;database=库名;uid=数据库账号;pwd=数据库密码"; //SQL server身份验证方法
SqlConnection connect = new SqlConnection(connectStr);
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
使用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");
}
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”);
DataRow类的RowState属性
DataRowState.Added 已添加
DataRowState.Deleted 已删除
DataRowState.Detached 已创建
DataRowState.Modified 已修改
DataRowState.Unchanged 未更改
一般在成功更新数据源之后调用AcceptChanges()方法
调用DataAdapter对象的Update( )方法,把这个变化返回到数据库中
thisAdapter.Update(thisDataSet, “Stu”);
没讲
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();
}
}
}
public class List { }
public class LinkedList { }
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; }
}
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; }
}
不能假定类提供了什么类型
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。
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,这称为裸类型约束,
//表示一个泛型类型参数用作另一个类型参数的约束
泛型类型可以实现泛型接口,也可以派生自一个类
泛型类可以派生自泛型基类
public class LinkedList<T> : IEnumerable<out T>
{
……
}
public class Base<T>{……}
public class Derived<T>: Base<T>{……}
泛型类的静态成员只能在类的一个实例中共享
public class StaticDemo<T>
{
public static int x;
}
StaticDemo<string>.x=4;
StaticDemo<int>.x=5;
Console.WriteLine(StaticDemo<string>.x); //输出4
//隐式转换
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;
}
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);
}
Nullable<int> x;//1
int? x2;//2
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);
如果类是泛型的,就必须为泛型方法类型使用不同的标识符
泛型方法可以重载,为特定的类型定义规范
public class MethodOverloads {
public void Foo<T>(T obj) {
Console.WriteLine("Foo(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值不会改变这一点
public int MyProp{ get; set; }
<className> <variableName>=new <className>
{
<propertyOrField1>=<value1>,
<propertyOrField2>=<value2>,
……
<propertyOrFieldN>=<valueN>
}
var varName = value;
匿名方法
匿名方法纯粹是为了委托目的而创建
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;
});