C#基础

static void Main1()
        {
            //通过委托开启一个线程
            Action a = Test1;
            a.BeginInvoke(null, null);//开启一个新的线程去执行a所引用的方法
            Console.WriteLine("main");//启动方法之后,先输出了main,再输出test
            Console.ReadKey();
        }
        static void Test1()
        {
            Console.WriteLine("test");
        }
线程的简单使用(调用无参无返回值的方法)
static void Main2()
        {
            //通过委托开启一个线程
            Action<string, int> a = Test2;
            a.BeginInvoke("vichin", 27, null, null);//开启一个新的线程去执行a所引用的方法,"vichin"和27是调用Test2时,所需要传入的参数。
            Console.WriteLine("main");//启动方法之后,先输出了main,再输出test
            Console.ReadKey();
        }
        static void Test2(string name, int age)
        {
            Console.WriteLine("My name is {0}。My age is {1}", name, age);
        }
线程的简单使用(调用有参无返回值的方法)
   
    static void Main3()
        {
            //通过委托开启一个线程
            Func<string, int, string> a = Test3;
            //声明一个变量iar来取得当前线程的状态。
            //BeginInvoke参数中:
            //"vichin"和27是调用Test3时所需要传递的参数。
            //第三个参数是一个委托,表示当a线程结束的时候会调用该方法。
            //第四个参数是用来传递数据给回调函数的。该数据可以是任何类型的。(只要是继承了Object了就行。该demo中是将一个委托对象传递了过去。接收时需要作类型转换。)
            IAsyncResult iar = a.BeginInvoke("vichin", 27, null, null);//开启一个新的线程去执行a所引用的方法            

            #region 使用一个死循环来检测副线程是否执行完毕
            //while (!iar.IsCompleted)
            //{
            //    Console.WriteLine("副线程还没有执行完毕");
            //}
            //string result = a.EndInvoke(iar);
            //Console.WriteLine(result);
            #endregion

            #region 使用等待句柄来检测副线程是否执行完毕。因为在a.BeginInvoke方法中传递了回调函数,所以下面这段代码就没有用了。
            //若WaitOne返回的是true,则表示副线程已经运行结束,否则表示没有结束。
            bool isDone = iar.AsyncWaitHandle.WaitOne(5000);//设置一个等待时间,检测是否超时。
            if (isDone)
            {
                string result = a.EndInvoke(iar);
                Console.WriteLine(result);
            }
            #endregion
            Console.WriteLine("main");//启动方法之后,先输出了main,再输出test
            Console.ReadKey();
        }
        static string Test3(string name, int age)
        {
            return "My name is " + name + ", My age is " + age.ToString();
        }

//使用回调函数
        static void Main3()
        {
            //通过委托开启一个线程
            Func<string, int, string> a = Test3;
            //声明一个变量iar来取得当前线程的状态。
            //BeginInvoke参数中:
            //"vichin"和27是调用Test3时所需要传递的参数。
            //第三个参数是一个委托,表示当a线程结束的时候会调用该方法。
            //第四个参数是用来传递数据给回调函数的。该数据可以是任何类型的。(只要是继承了Object了就行。该demo中是将一个委托对象传递了过去。接收时需要作类型转换。)
            IAsyncResult iar = a.BeginInvoke("vichin", 27, CallBackFunction, a);//开启一个新的线程去执行a所引用的方法            
            Console.WriteLine("main");//启动方法之后,先输出了main,再输出test
            Console.ReadKey();
        }
        static string Test3(string name, int age)
        {
            return "My name is " + name + ", My age is " + age.ToString();
        }
        /// <summary>
        /// 副线程的回调函数
        /// </summary>
        /// <param name="ar">副线调用该方法时,会自动传递IAsyncResult类型的参数</param>
        static void CallBackFunction(IAsyncResult iar)
        {
            Func<string, int, string> a = iar.AsyncState as Func<string, int, string>;
            string result = a.EndInvoke(iar);
            Console.WriteLine("在回调函数中取得结果,结果是:" + result);
            Console.WriteLine("副线程运行结束,调用了该回调函数。");
        }

//使用委托(lambda表达式)
        static void Main3()
        {
            //通过委托开启一个线程
            Func<string, int, string> a = Test3;
            //声明一个变量iar来取得当前线程的状态。
            //BeginInvoke参数中:
            //"vichin"和27是调用Test3时所需要传递的参数。
            //第三个参数是一个委托,表示当a线程结束的时候会调用该方法。
            //第四个参数是用来传递数据给回调函数的。该数据可以是任何类型的。(只要是继承了Object了就行。该demo中是将一个委托对象传递了过去。接收时需要作类型转换。)
            a.BeginInvoke("vichin", 27, iar =>
            {
                string result = a.EndInvoke(iar);
                Console.WriteLine("副线程执行完毕,结果是:" + result+"。    本段代码是在lambda表达式中执行的!");
            }, null);//开启一个新的线程去执行a所引用的方法            
            Console.WriteLine("main");//启动方法之后,先输出了main,再输出test
            Console.ReadKey();
        }
        static string Test3(string name, int age)
        {
            return "My name is " + name + ", My age is " + age.ToString();
        }
线程的简单使用(调用有参有返回值的方法)

 

事件:

    public class Incrementer
    {
        /*
         * 事件是类或结构的成员,跟方法属性一样         
         *      由于事件是成员,所以不能在一段可执行的代码中声明事件。
         *      必须声明在类或结构中,和其他成员一样。
         * 事件成员被隐式自动初始化为null。 
         */
        //public event EventHandler Event1, Event2, Event3;//一次性声明多个事件        
        //public static event EventHandler StaticEvent;//使用static关键字让事件变成静态

        /// <summary>
        /// event 关键字
        /// EventHandler 委托类型
        /// CountedADozen 事件名
        /// </summary>
        public event EventHandler CountedADozen;//发布事件

        public void DoCount()
        {
            CountedADozen(this, null);//调用事件 触发事件时使用EventHandler的参数。
        }
    }

    class Dozens
    {
        public int DozensCount { get; set; }

        public Dozens(Incrementer incrementer)
        {
            DozensCount = 0;
            incrementer.CountedADozen += IncrementDozensCount;//订阅一个事件
        }

        /// <summary>
        /// 事件实际执行的代码。
        /// 事件处理程序的签名必须与委托的签名匹配
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        void IncrementDozensCount(object source, EventArgs e)
        {
            DozensCount++;
        }
    }

        private void button1_Click(object sender, EventArgs e)
        {        
            Incrementer incrementer =new Incrementer ();            
            Dozens dozensCounter = new Dozens(incrementer);
            incrementer.DoCount();//执行了事件
            MessageBox.Show(dozensCounter.DozensCount.ToString());
        }
事件的简单实用

 

    public class IncrementerEventArgs : EventArgs
    {
        public int IterationCount { get; set; }//存一个整数
    }
    
    public class Incrementer
    {
        public event EventHandler<IncrementerEventArgs> CountedADozen;
        public void DoCount()
        {
            IncrementerEventArgs arg = new IncrementerEventArgs();
            arg.IterationCount = 1;
            CountedADozen(this, arg);//传递参数,谁订阅了这个事件,下一步就会去执行谁的代码。
            Console.WriteLine("事件被执行了");
        }
    }


    class Dozens
    {
        public int DozensCount { get; set; }

        public Dozens(Incrementer incrementer)
        {
            DozensCount = 0;
            incrementer.CountedADozen += IncrementDozensCount;
        }
        
        void IncrementDozensCount(object source, IncrementerEventArgs e)//这里参数的类型与之前不一样,发生了变化
        {
            DozensCount++;
            Console.WriteLine("订阅的被执行了");
        }
    }


        static void Main(string[] args)
        {
            Incrementer incrementer = new Incrementer();
            Dozens dozensCounter = new Dozens(incrementer);
            incrementer.DoCount();//执行了事件  
            Console.ReadKey();
        }
事件传递更多参数

 

委托:

 delegate int MyDel();//声明委托  委托返回值是int类型,委托的类型的MyDel类型的
    class MyClass
    {
        int valInt = 5;
        public int Add2()
        {
            valInt += 2;
            return valInt;
        }
        public int Add3()
        {
            valInt += 3;
            return valInt;
        }
    }
声明委托 和 类

 

            MyClass mc = new MyClass();
            MyDel md = mc.Add2;//创建并初始化委托
            md += mc.Add3;//增加方法
            md();//一次性会调用两个方法
            md -= mc.Add2;//减掉一个方法    
调用(使用)委托

 

delegate int MyDel(int para);

public partial class A : WebPageBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            MyDel del = delegate(int x)     { return x + 1; };//使用匿名方法声明委托
            MyDel le1 =         (int x) =>  { return x + 1; };//lambda表达式
            MyDel le2 =             (x) =>  { return x + 1; };//lambda表达式
            MyDel le3 =              x  =>  { return x + 1; };//lambda表达式
            MyDel le4 =              x  =>           x + 1;   //lambda表达式
        }
    }
委托 到 lambda表达的演变过程

lambda表达式的(c#编程指南) 

 

委托的实际应用(在窗体之间,传递方法:有点调用一个公共方法的意思。)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace FormDelegate
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            deliver dl = new deliver(UpdateValue);
            //dl += UpdateValue;
            Form2 form2 = new Form2(textBox1.Text.Trim(), UpdateValue);//调用窗体2的时候,会将窗体1内的文本值和UpdateValue方法传递给了Form2
            form2.Show();
        }
        void UpdateValue(string val)
        {
            this.textBox1.Text = val;
        }
        public delegate void deliver(string val);
    }
}
Form1中的代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace FormDelegate
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        public Form2(string n, FormDelegate.Form1.deliver updateVale)
            : this()//这里创建一个新的构造函数,让它继承默认的构造函数。若是不继承,那么InitializeComponent方法就没有执行,会导致控件没被初始化
        {
            this.textBox1.Text= n;
            this.dlv = updateVale;
        }

        private FormDelegate.Form1.deliver dlv;//声明一个deliver类型的变量,用于接收form1传递过来的方法。
        private void button1_Click(object sender, EventArgs e)
        {
            this.dlv(textBox1.Text.Trim());//将Form2内的文本框中的值,更新到form1的文本框中。
            this.Close();
        }

    }
}
Form2中的代码

 

 

构造函数:

 class Car
    {
        //car 的状态
        public string petName;
        public int currSpeed;
        //构造函数是类的特殊方法。构造函数永远都不会有返回值,并且它的名字总是和需要构造的类的名字相同。
        public Car(string name, int spd)
        {
            petName = name;
            currSpeed = spd;
        } 
        //Car的功能
        public void PrintState()
        {
            Console.WriteLine("{0} is going {1} MPH.", petName, currSpeed);
        }
        public void SpeedUp(int delta)
        {
            currSpeed += delta;
        }             
    }
构造函数

使用了构造函数之后,就可以在创建对象的时候,直接为对象的属性赋值了对象初始化语法声明变量

ctor+tab+tab:快速生成构造函数

 

public Student(string name,int age,int height,string sid) : base(name,age,height){
    this.Sid=sid;
}
子类继承父类的构造函数

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WebApplication1
{
    public class Person
    {



        public int Age { get; set; }

        public string Name { get; set; }
        public int Height { get; set; }
        public string Email { get; set; }



        public Person(string name, int age, int height, string email)
        {
            this.Name = name;
            this.Age = age;
            this.Height = height;
            this.Email = email;
        }

        /// <summary>
        /// 传入name和age
        /// </summary>
        /// <param name="name"></param>
        /// <param name="age"></param>
        public Person(string name, int age) : this(name, age, 0, string.Empty) { }
        /// <summary>
        /// 创建对象时传入name和email这两个参数
        /// </summary>
        /// <param name="name"></param>
        /// <param name="email"></param>
        public Person(string name, string email)
            : this(name, 0, 0, email)
        {

        }
    }
}
使用this调用构造函数

 

每一个类都有一个默认的构造函数(无参数的),每个类的构造函数是不能被继承的

 

 

封装

class Employee
    {
        string empName;
        int empID;
        float currPay;
        public string Name
        {
            get { return empName; }
            set
            {
                if (value.Length > 15)
                    Console.WriteLine("Error! Name must be less than 16 characters!");
                else
                    empName = value;

            }
        }
        public int ID { get; set; }
    }
封装的目的在于不让外界访问到对象的内部属性(在这里就是 empName、empID和currPay)。外界可以访问到的是Name和ID。在调用的地方给Name赋值的时候,可以让Employee自己内部
对这个值进行检查(这里让我感觉,empName变量的存在就是为Name服务的)。set语句块负责提供检查逻辑。
如果不需要检查值的话(打包类的业务规则),可以直接使用自动属性{get;set;},而且,不需要创建额外字段。
封装

prop + tab+tab  :快速构造自动属性

propfull +tab+tab:快速构造 字段+属性

态:把不同的子类对象,都当作父类来看待。可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程以适应需求的不断变化。

virtual   override  sealed

 

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

namespace ConsoleApplication1
{
    public class Person
    {
        public int Age { get; set; }
        public string Name { get; set; }
        public Person(string name, int age)
        {
            this.Age = age;
            this.Name = name;
        }
        public virtual void SayHi()
        {
            Console.WriteLine("NI HAO");
        }
    }
}
父类person.cs

 

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

namespace ConsoleApplication1
{
    public class Chinese : Person
    {       
        public string Sex { get; set; }
        public Chinese(string name, string sex, int age)
            : base(name, age)
        {
            this.Sex = sex;
        }
        public override void SayHi()
        {
            Console.WriteLine("你好!");
        }
    }
}
子类chinese.cs
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace ConsoleApplication1
 7 {
 8     public class American : Person
 9     {
10         public string Sex { get; set; }
11         public American(string name, string sex, int age)
12             : base(name, age)
13         {
14             this.Sex = sex;
15         }
16         public override void SayHi()
17         {
18             Console.WriteLine("Hello!");
19         }
20     }
21 }
子类american.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Person[] psn = new Person[2];
            psn[0] = new Chinese("陈伟", "", 25);
            psn[1] = new American("vichin", "M", 25);
            for (int i = 0; i < psn.Length; i++)
            {
                Console.WriteLine(psn[i].Name);
                Console.WriteLine(psn[i].Age);
                psn[i].SayHi();
                //第一次是:
                            //陈伟
                            //25
                            //你好!
                //第二次是:
                            //vichin
                            //25
                            //Hello!
            }
            Console.ReadKey();
        }
    }
}
主程序代码

 

 

如果不想让孙子类改变儿子类中的那些重写的方法,可以在儿子类中的那些重写的方法上增加sealed(密封),将方法密封起来。

这是一个儿子类中的方法
public override sealed void GiveBonus(float amount) { int salesBonus = 0; }

sealed关键字也可以用来密封类,如果在类前面加了这个关键字,那么该类就不能继承。

sealed class Person{
  string name{get;set;}
  int age{get;set;}    
}


//写成下面这样,VS就会报错
class Teacher:Person{
…………
}
使用sealed关键字来密封类

 抽象类 abstract

 在类的前面使用abstract后,该类就不能被实例化了。他只提供其他类的继承的接口。

 比如。我们的老爹类中有一些原始的方法,这些方法都需要在子孙类中,进行二次加工之后,才能拿出来用的。这个时候,abstract关键字就起作用了。

抽象方法 abstract

 抽象方法只能定义在抽象类中。抽象方法中只定义名字,返回值(可以没有返回值)和参数(可以没有参数)

抽象类可以包含abstract方法,也可包含实例化方法,但继承的类(非抽象类)必须实现abstract方法

 

 接口:抽象成员的命名集合。一个接口最好只包含一个方法,当某个类被实例化的时候,就可以直接用那个类去继承这个接口。

只有类和结构才能实现接口。接口中的所有成员必须被继承者一一实现。

可以同时继承多个接口,这是类所不具备的。

 

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

namespace ConsoleApplication1
{
    interface IIfac1
    {
        void PrintOut(string s);//分号代替方法体
    }
}
//接口中的方法,默认是public,而非private。void前面不能写public/private或者protect等修饰符
接口

 

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

namespace ConsoleApplication1
{
    class MyClass : IIfac1
    {
        public void PrintOut(string s)//实现接口中的声明的方法
        {
            Console.WriteLine("Calling through: {0}", s);
        }
    }
}
继承了接口的类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass mc = new MyClass();
            mc.PrintOut("Hello Word");//调用方法
        }
    }
}
具体实现

 

泛型:让多个类共享一组代码。泛型允许我们声明类型参数化的代码,可以用不同的类型进行实例化。

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

namespace ConsoleApplication1
{
    class MyStack<T>
    {
        T[] StackArray;
        int StackPointer = 0;
        public void Push(T x)
        {
            if (!IsStackFull)
                StackArray[StackPointer++] = x;
        }
        public T Pop()
        {
            return (!IsStackEmpty) ? StackArray[--StackPointer] : StackArray[0];
        }
        const int MaxStack = 10;
        bool IsStackFull { get { return StackPointer >= MaxStack; } }
        bool IsStackEmpty { get { return StackPointer <= 0; } }
        public MyStack()
        {
            StackArray = new T[MaxStack];
        }
        public void Print()
        {
            for (int i = StackPointer - 1; i >= 0; i--)
            {
                Console.WriteLine("  Value:{0}", StackArray[i]);
            }
        }
    }
}
实例____类

 

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MyStack<int> StackInt = new MyStack<int>();
            MyStack<string> StackString = new MyStack<string>();
            StackInt.Push(3);
            StackInt.Push(5);
            StackInt.Push(7);
            StackInt.Push(9);
            StackInt.Print();
            StackString.Push("This is fun");
            StackString.Push(" HI here");
            StackString.Print();
        }
    }
}
实例____使用泛型

 

使用 Where 字句来对泛型类进行约束 

 

class MyClass <T>  where T:Customer{
         ……                  
}



    class MyClass<T, T1, T2> where T1 : Customer where T2:IEnumerable
    {
                                 //T1的约束      //T2的约束 
    }

    class Customer
    {

    }
泛型约束

 

约束的5种类型:

类名: 只有这个类型的类或者从它继承的类才能用作类型实参。

class:任何引用类型,包括类,数组,委托和接口都可以用作类型实参。

struct:任何值类型都可以用作类型实参。

接口名:只有这个接口或者实现这个接口的类型才能用作类型实参。

new():任何带有无参数公共构造函数的类型都可以用作类型实参。这叫做构造函数约束。

where 字句中,约束的顺序

1,、最多只能有一个主约束,如果有则必须放在第一位。

2、可以有多个接口名约束。

3、如果存在构造函数,则必须放在最后。

 

泛型方法

 public void PrintData<S, V>(S p, V v) where S : Person
        {
            //<S,V>:类型参数列表
            //(S p,V v)方法参数列表
        }
泛型方法签名说明

 

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

namespace myFunc
{
    class Simple
    {
        static public void ReverseAndPrint<T>(T[] ary)//泛型方法
        {
            Array.Reverse(ary);
            foreach (T item in ary)//使用类型参数T
            {
                Console.Write("{0},", item.ToString());                
            }
            Console.WriteLine(" ");
        }
    }
}
泛型方法

 

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

namespace myFunc
{
    class Program
    {
        static void Main(string[] args)
        {
            var intAry = new int[] { 3, 5, 7, 9, 11 };
            var stringAry = new string[] { "first", "second", "third" };
            var doubleAry = new double[] { 3.567, 7.891, 2.345 };
            Simple.ReverseAndPrint<int>(intAry);//调用方法
            Simple.ReverseAndPrint(intAry);//推断参数intAry的类型,并调用

            Simple.ReverseAndPrint<string>(stringAry);//调用方法
            Simple.ReverseAndPrint(stringAry);//推断参数intAry的类型,并调用

            Simple.ReverseAndPrint<double>(doubleAry);//调用方法
            Simple.ReverseAndPrint(doubleAry);//推断参数intAry的类型,并调用
            Console.ReadKey();
        }
    }
}
泛型方法的使用

 

在操作集合的时候,会频繁的做拆箱、装箱,所有性能不如泛型来的高。

//值类型自动装箱
ArrayList myInts=new ArrayList();
myInts.Add(10);
myInts.Add(20);
myInts.Add(30);

int i=myInts[0]; //拆箱
集合的拆、装箱

  

始化器:

person p2 = new person { age = 25, name = "curry" };
对象初始化器
    List<Product> proList = new List<Product> { 
        new Product { ProductID = 1234, Name = "西瓜", Price = 2.3M },
        new Product { ProductID = 2345, Name = "苹果", Price = 5.9M  },
        new Product { ProductID = 3456, Name = "樱桃", Price = 4.6M }
    };
集合初始化器
string[] fruitArray = {"apple","orange","plum" };
数组使用初始化器
var books = new { Title = "ASP.NET MVC 入门", Author = "小王", Price = 20 };
匿名类使用初始化器
Dictionary<string, int> fruitDic = new Dictionary<string, int>() { 
    { "apple", 10 },
    { "orange", 20 },
    { "plum", 30 }
};
字典使用初始化器

 

 拓展方法:

class person
    {
        public string name { get; set; }
        public int age { get; set; }
        public void eat()
        {
            Console.WriteLine("having dinner");
        }
    }

//person类中并没有driving这个方法。
person类代码
 person p2 = new person { age = 25, name = "curry" };
            p2.eat();
            p2.Driving();
拓展方法被调用的代码
public static class MyExtentsionMethods
    {
        public static void Driving(this person people)
        {
            Console.WriteLine("I like BMW");
        }
    }
拓展方法的代码

拓展方法必须为静态方法(静态方法只能出现在静态类中)。

第一个参数person类的前面有一个this,将driving标注为静态方法。

 泛型委托

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

namespace myFunc
{
    public delegate TR Func<T1, T2, TR>(T1 para1, T2 para2);//泛型委托
    //T1、T2是传入参数类型,TR是返回类型
    //参数类型列表(尖括号中的参数)至少需要两个,一个是传入类型,一个是返回类型

    class Simple
    {
        static public string PrintStr(int para1, int para2)//方法匹配委托
        {
            int total = para1 + para2;
            return total.ToString();
        }        
    }
}
声明泛型委托

 

 var myDel = new Func<int, int, string>(Simple.PrintStr);//创建委托实例
            Console.WriteLine("Total:{0}", myDel(15, 13));//调用委托
调用泛型委托

 泛型接口

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

namespace myFunc
{
    interface IMyIfc<T>//泛型接口
    {
        T ReturnIt(T inValue);
    }
}
声明返现接口

 

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

namespace myFunc
{
    public delegate TR Func<T1, T2, TR>(T1 para1, T2 para2);//泛型委托
    //T1、T2是传入参数类型,TR是返回类型
    //参数类型列表(尖括号中的参数)至少需要两个,一个是传入类型,一个是返回类型

    class Simple : IMyIfc<string>, IMyIfc<int>//源于同一个泛型接口的两个不同接口。。。。simple——非泛型类
    {
        public int ReturnIt(int inValue)//实现int类型接口
        {
            return inValue;
        }
        public string ReturnIt(string inValue)//实现string类型接口
        {
            return inValue;
        }
    }
}
声明类,继承接口

 

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

namespace myFunc
{
    class Program
    {
        static void Main(string[] args)
        {
            Simple trival = new Simple();
            Console.WriteLine("{0}", trival.ReturnIt(5));
            Console.WriteLine("{0}", trival.ReturnIt("Hi there"));
            Console.ReadKey();
        }
    }
}
调用

 

线程

给线程传递参数可以采用两种方式:
1、使用带ParameterizedThreadStart委托参数的Thread的构造函数。
2、创建自定义类,把线程的方法定义为实例方法,这样就可以初始化实例的数据,再去启动某个线程

//1、使用带ParameterizedThreadStart委托参数的Thread的构造函数。
    //定义一个类型用来传递数据
    public struct Data
    {
        public string Message;
    }
    //定义一个方法,用来开启一个线程并执行这个方法
    private static void ThreadMainWithParameters(object obj)
    {
        Data d = (Data)obj;
        Console.WriteLine("Running  in a thread,received:{0}", d.Message);
    }
    //主程序
     static void Main(string[] args)
    {   
         var d = new Data { Message = "My name is vichin!" };
         var t2 = new Thread(ThreadMainWithParameters);
        t2.Start(d);
        Thread.Sleep(1);
        Console.ReadKey();
    }

//2、创建自定义类,把线程的方法定义为实例方法,这样就可以初始化实例的数据,再去启动某个线程
    //定义一个类
    public class MyThread
    {
        private string data;
        public MyThread(string _data)
        {
            data = _data;
        }

        public void ThreadMain(object obj)
        {
            Console.WriteLine("Running in a thread,data:{0}", data);
        }
    }

    //主程序
     static void Main(string[] args)
     {
         var obj = new MyThread("info");
         var t3 = new Thread(obj.ThreadMain);
         t3.Start();          
     }

在默认情况下,Thread类创建的线程都是前台线程。当主线程的方法运行完了之后,前台线程若是没有运行完,那么整个进程也不会被关闭。
如果想要主线程运行完就关闭整个进程(副线程也要关闭,而不是等待运行完了之后再关),可以考虑创建后台线程。
    //创建后台线程
    //t3.IsBackground = true;

线程在start()方法之后并不是处于running状态了(状态为unstarted),而是在操作系统调度器用它的时候才会running
Thread.Join()会停止当前线程,并在加入进来的线程完成之后继续执行当前线程
死锁:两个线程挂起,并且同时等待对方解除锁定.
线程的简单使用1

  默认使用thread类产生的线程都是前台线程,使用线程池ThreadPool产生的线程都是后台线程。

  当所有的前台线程运行完毕,如果还有后台线程运行的话,所有的后台线程会被终止。

  当存在多个线程的时候,可以为每一个线程设置优先级(thread的Priority属性),让计算机去执行它们。(ThreadPriority枚举中存在Highest,AboveNormal,BelowNormal和Lowest)。

  线程在创建之初为Unstarted状态,调用Start方法的时候仍然处于Unstarted状态。当操作系统任务调度器运行线程的时候,这个线程的状态才会变成Running状态。当我们使用Sleep方法的

  时候,线程的状态会变更为WaitSleepJoin状态。 

        static void Main(string[] args)
        {
            #region 创建线程1(方法名当做参数传入)
            //Thread t = new Thread(DownLoad);
            //t.Start();
            #endregion

            #region 创建线程2(使用lambda表达式)
            Thread t = new Thread(() =>
            {
                Console.WriteLine("开始下载,当前线程ID:" + Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(2000);
                Console.WriteLine("下载完成");
            });
            t.Start("我正在学习开启线程,并向方法中传递数据");
            #endregion

            Console.ReadKey();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="msg">只接收object类型的参数</param>
        static void DownLoad(object msg)
        {
            Console.WriteLine("开始下载,传入的信息是:{0},当前线程ID:{1}", msg, Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(2000);
            Console.WriteLine("下载完成");
        }
线程的简单使用2(使用Thread类创建线程)

 

线程池中所有的线程都是后台线程,如果所有的前台线程都结束了,所有的后台线程就会停止。
不能把入池的线程改为前台线程。不能修改入池线程的优先级与名称。
入池的线程只能用于用时较短的任务。如果线程一直运行就应该使用Thread类来创建一个线程。

        static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(ThreadMethod);//开启一个工作线程
        }

        static void ThreadMethod(object state)
        {
            Console.WriteLine("线程开始");
            Thread.Sleep(2000);
            Console.WriteLine("线程结束");
        }
线程的简单使用3(ThreadPool)

 

  • ThreadPool不支持线程的取消、完成、失败通知等交互性操作;
  • ThreadPool不支持线程执行的先后次序;

Task看起来像一个Thread,实际上,它是在ThreadPool的基础上进行的封装,Task的控制和扩展性很强,在线程的延续、阻塞、取消、超时等方面远胜于ThreadThreadPool。

        static void Main(string[] args)
        {
            #region 开启任务的第一种方法
            Task t = new Task(ThreadMethod);//传递一个需要线程去执行的方法。
            t.Start();
            t.Wait();

            #endregion



            #region 开启任务的第二种方法
            TaskFactory tf = new TaskFactory();
            Task t1 = tf.StartNew(ThreadMethod);
            #endregion

            #region 连续任务的使用。(在运行完t1任务之后,便同时运行t2和t3这两个任务。)
            Task t2 = t1.ContinueWith(DoSth);
            Task t3 = t1.ContinueWith(DoSth);

            Task.WaitAll(t2, t3);//等待所有任务执行完成,
            Task.WaitAny(t2, t3);//等待任意一个执行成功
            #endregion
        }

        static void ThreadMethod()
        {
            Console.WriteLine("任务开始");
            Thread.Sleep(2000);
            Console.WriteLine("任务结束");
        }
        static void DoSth(Task t)
        {
            Console.Write("连续任务!");
        }
线程的简单使用(task)

 

反射

//反射当前项目中的类
            Assembly assembly = Assembly.GetExecutingAssembly(); // 获取当前程序集 
            object obj = assembly.CreateInstance("类的完全限定名(即包括命名空间)"); // 创建类的实例,返回为 object 类型,需要强制类型转换

//创建类的实例时,传入参数
                Assembly assembly = Assembly.GetExecutingAssembly();
                object[] ParaAry = { strModelFun, this };
                Form obj = (Form)assembly.CreateInstance("nameSpace." + className, true, System.Reflection.BindingFlags.Default, null, ParaAry, null, null);// 创建类的实例 
                obj.Show();



            //跨程序集反射
            Assembly assembly = Assembly.LoadFile().CreateInstance("类的完全限定名(即包括命名空间)");
            //LoadFile与后面的两者有所不同,它不会加载此程序集引用的其他程序集,也就是不会加载程序的依赖项。此外它和LoadForm一样,不能加载同标识不同路径的程序集


            Assembly assembly1 = Assembly.LoadFrom().CreateInstance("类的完全限定名(即包括命名空间)");
            //"D:\\workspace\\LatestWebTestSite\\TestLib.dll"

            Assembly assembly2 = Assembly.Load().CreateInstance("类的完全限定名(即包括命名空间)");            
            //"TestLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" 程序集的长格式。

            //LoadForm和Load方法的相同点:LoadForm和Load方法会将所要加载的程序集的依赖项一起加载进来。
            //                    不同点:LoadFrom只能用于加载不同标识的程序集, 也就是唯一的程序集, 不能用于加载标识相同但路径不同的程序集







        //反射的一种用法
        public T xmltoT<T>() where T : class, new()
        {
            T t = new T();
            //GetType()会返回一个T类型的实例。GetProperties方法会返回T类型的属性。GetFields返回字段.GetMethods返回方法名称
            var items = t.GetType().GetProperties();
            foreach (var item in items)
            {
                item.SetValue(t, "要赋的值", null);
            }
            var itemMethods = t.GetType().GetMethods();
            foreach (var item in itemMethods)
            {

            }
            return t;
        }
反射——动态创建对象并调用对象的方法

 

补充:跨程序集反射

如果我们反射A.dll,而A.dll中引用了B.dll,那么在assembly.GetTypes(); //运行到这个地方会弹出如下错误描述 

“未处理 System.Reflection.ReflectionTypeLoadException Message="无法加载一个或多个请求的类型。有关更多信息,请检索LoaderExceptions属性。”

 

这种情况可以:

Assembly assembly =  Assembly.LoadFrom("A.dll") ;
Type type = assembly.GetType("xxx.myclassname") ; //传入对应的需要反射的类型 而不能GetTypes。且,应用程序需要应用A.dll锁依赖的B.dll。

 

 

 

依赖注入(片段)

出处:http://www.cnblogs.com/zhaopei/p/5078539.html

我们有没有发现。我们只是在DAL新增了一个mysql的实现和修改了下UI层的接口构造。其中BLL我们根本就没有动它的。

是的,这样我们就可以说这里的UI对于BLL来说就是”依赖注入“,BLL对于UI来说就是”控制反转“。所以,我觉得依赖注入和控制反转是同一个概念,只是立场不同。

 //没有使用依赖注入
            ISqlHelper sqlhelper = new DALMsSqlHelper();
            BLLAddStudent s = new BLLAddStudent(sqlhelper);
            s.addStudent();
//当sqlHelper对象不要指向DALMsSqlHelper类的时候,就需要重新改动代码,当改动多的时候,就要出问题。


            //使用依赖注入
            string dllNameStr = "";//从配置文件中获取到名字,以后要改的话,只需要改名字就行了。
            Assembly asm2 = Assembly.LoadFrom("DAB.DLL");
            ISqlHelper SQLHELPERR = (ISqlHelper)asm2.CreateInstance("net.DalMySqlHelper", true);//net.DalMySqlHelper 这个字符串将从webConfig中获取
            SQLHELPERR.add("string para");
//当SQLHELPERR实例不要指向DalMySqlHelper对象的时候,只需要更改webConfig内的配置即可。
使用与未使用依赖注入的对比

 

给线程传递参数可以采用两种方式:
1、使用带ParameterizedThreadStart委托参数的Thread的构造函数。
2、创建自定义类,把线程的方法定义为实例方法,这样就可以初始化实例的数据,再去启动某个线程

//1、使用带ParameterizedThreadStart委托参数的Thread的构造函数。
    //定义一个类型用来传递数据
    public struct Data
    {
        public string Message;
    }
    //定义一个方法,用来开启一个线程并执行这个方法
    private static void ThreadMainWithParameters(object obj)
    {
        Data d = (Data)obj;
        Console.WriteLine("Running  in a thread,received:{0}", d.Message);
    }
    //主程序
     static void Main(string[] args)
    {   
         var d = new Data { Message = "My name is vichin!" };
         var t2 = new Thread(ThreadMainWithParameters);
        t2.Start(d);
        Thread.Sleep(1);
        Console.ReadKey();
    }

//2、创建自定义类,把线程的方法定义为实例方法,这样就可以初始化实例的数据,再去启动某个线程
    //定义一个类
    public class MyThread
    {
        private string data;
        public MyThread(string _data)
        {
            data = _data;
        }

        public void ThreadMain(object obj)
        {
            Console.WriteLine("Running in a thread,data:{0}", data);
        }
    }

    //主程序
     static void Main(string[] args)
     {
         var obj = new MyThread("info");
         var t3 = new Thread(obj.ThreadMain);
         t3.Start();          
     }

在默认情况下,Thread类创建的线程都是前台线程。当主线程的方法运行完了之后,前台线程若是没有运行完,那么整个进程也不会被关闭。
如果想要主线程运行完就关闭整个进程(副线程也要关闭,而不是等待运行完了之后再关),可以考虑创建后台线程。
    //创建后台线程
    //t3.IsBackground = true;

线程在start()方法之后并不是处于running状态了(状态为unstarted),而是在操作系统调度器用它的时候才会running
Thread.Join()会停止当前线程,并在加入进来的线程完成之后继续执行当前线程
死锁:两个线程挂起,并且同时等待对方解除锁定.


_______________________________________________________________________________________________________________________________
进程:构成运行程序的资源的集合(虚地址空间、文件句柄……)
默认情况下一个进程值包含一个线程
线程可以派生其他线程。
若一个进程中包含多个线程,那么他们就共享进程的资源。
系统为处理器执行所规划的单元是线程。而非进程。

异步方法:
1、方法头中包含async方法修饰符
2、在方法中包含一个或多个await表达式。
3、方法的返回列表必须是Task、Task<T>或void
4、方法的参数列表中不能有out或者ref传参
5、异步方法的方法名一般以Async结尾
6、除方法外,Lambda表达式和匿名方法也可以作为异步对象

namespace ConsoleApplication1
{
    public class MyDownLoadString
    {
        Stopwatch sw = new Stopwatch();
        public void DoRun()
        {
            const int LargeNumer = 6000000;
            sw.Start();
            //异步编程,首先t1 t2和CountToALarageNumber(1, LargeNumer);这3个对象在各自运行的时候,都不会影响到对方,因此,可以使用异步编程。
            //创建t1对象后,不会立即运行Countcharacters中代码,而是继续走到下一行,创建t2。t2和t1一样,也不会走Countcharacters而是继续走下一行代码CountToALarageNumber方法
            Task<int> t1 = Countcharacters(1, "http://www.microsoft.com");
            Task<int> t2 = Countcharacters(2, "http://www.illustratedcsharp.com");
            CountToALarageNumber(1, LargeNumer);
            CountToALarageNumber(2, LargeNumer);
            CountToALarageNumber(3, LargeNumer);
            CountToALarageNumber(4, LargeNumer);
            Console.WriteLine(" Chars in http://www.microsoft.com    :{0}", t1.Result);//t1.result暂且认为是执行Countcharacters方法后返回的值。
            Console.WriteLine(" Chars in http://www.illustratedcsharp.com    :{0}", t2.Result);
        }

        private void CountToALarageNumber(int id, int value)
        {
            for (long i = 0; i < value; i++) ;
            Console.WriteLine(" End counting {0}    :       {1}ms", id, sw.Elapsed.TotalMilliseconds);
        }

        //方法中包含了async
        //方法的返回值为Task<T>
        private async Task<int> Countcharacters(int id, string uriString)
        {
            WebClient wc1 = new WebClient();
            Console.WriteLine(" Starting call{0}   :    {1}ms", id, sw.Elapsed.TotalMilliseconds);
            //在方法中包含了至少一个await表达式
            string result = await wc1.DownloadStringTaskAsync(new Uri(uriString));
            Console.WriteLine(" Call {0} completed:{1}ms", id, sw.Elapsed.TotalMilliseconds);
            return result.Length;
        }
    }
}

主程序代码
        static void Main(string[] args)
        {
            MyDownLoadString ds = new MyDownLoadString();
            ds.DoRun();
            Console.ReadKey();
        }



//返回值为Task<T>的异步方法
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Task<int> value = DoAsyncStuff.CalculateSumAsync(5, 6);
            //这里可以去做其他的操作
            Console.WriteLine("value    :{0}", value.Result);
        }

    }
    static class DoAsyncStuff
    {       
        public static async Task<int> CalculateSumAsync(int p1, int p2)
        {
            int sum = await Task.Run(() => GetSum(p1, p2));//匿名方法 gos to 后面是返回值,返回值是GetSum方法
            return sum;
        }

        private static int GetSum(int p1, int p2)
        {
            return p1 + p2;
        }
    }
}


//返回值为Task的异步方法
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Task someTask = DoAsyncStuff.CalculateSumAsync(5, 6);
            //这里可以去做其他的操作
            someTask.Wait();
            Console.WriteLine("Async stuff is done");
            Console.ReadKey();
        }
    }
    static class DoAsyncStuff
    {       
        public static async Task<int> CalculateSumAsync(int p1, int p2)
        {
            int sum = await Task.Run(() => GetSum(p1, p2));
            return sum;
        }

        private static int GetSum(int p1, int p2)
        {
            return p1 + p2;
        }
    }
}


//返回值为void的异步方法
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            DoAsyncStuff.CalculateSumAsync(5, 6);
            //这里可以去做其他的操作
            Thread.Sleep(200);//挂起线程,以防下面的语句执行完毕之后,CalculateSumAsync方法还没执行完
            Console.WriteLine("Async stuff is done");            
        }
    }
    static class DoAsyncStuff
    {
        public static async void CalculateSumAsync(int p1, int p2)
        {
            int value = await Task.Run(() => GetSum(p1, p2));
            Console.WriteLine("value    :{0}", value);
        }

        private static int GetSum(int p1, int p2)
        {
            return p1 + p2;
        }
    }
}



namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Task t = (new MyClass()).DoWorkAsync();            
        }
    }   
    class MyClass
    {
        public int Get10()
        {
            return 10;
        }
        public async Task DoWorkAsync()
        {
            Func<int> ten = new Func<int>(Get10);
            int a = await Task.Run(ten);
            int b = await Task.Run(new Func<int>(Get10));
            int c = await Task.Run(() => { return 10; });
            Console.WriteLine("{0} {1} {2}", a, b, c);
        }
    }
}

//同步等待任务
Task t = (new MyClass()).DoWorkAsync();
Task t1=(new MyClass()).DoWorkAsync();
Task<int>[] tasks=new Task<int>[]{t,t1};

t.Wait();//等待t完成之后吗,再继续执行后面的代码
t.WaitAll();//等待一组任务全都完成之后,再继续执行。
t.WaitAny();//任意一个任务执行完成后,就往下执行。
//WaitAll和WaitAny有重载,可以指定超时时间。

//在异步方法中异步等待任务
//Task.WhenAll和Task.WhenAny
//CountCharsAsync是一个异步方法,在这个异步方法内,还存在等待异步方法的行为
async Task<int> CountCharsAsync(string site1,string site2){
    WebClient wc1=new WebClient();
    WebClient wc2=new WebClient();
    Task<string>t1=wc1.DownloadStringTaskAsync(new Uri(site1));
    Task<string>t2=wc2.DownloadStringTaskAsync(new Uri(site2));
    List<Task<string>> tasks=new List<Task<string>>();
    tasks.Add(t1);
    tasks.Add(t2);
    await Task.WhenAll(tasks);//异步等待任务完成
}
//使用Task.Delay可以延迟执行异步方法中的代码。并且它并不会像Thread.Sleep()那样将线程挂起!
async void ShowDelayAsync(){
    Console.WriteLine("before Delay");
    await Task.Delay(1000);//会创建一个task类型的对象在内存中,并在一定时间之后完成。
    Console.WriteLine("after Delay");
}
.net4.5中,异步编程的简单使用

一片有关C#异步编程的博客: https://blog.csdn.net/kebi007/article/details/76899078?locationNum=4&fps=1


 

 

 Thread.Sleep(2000);//2秒后再继续执行(线程挂起2秒)

 Response.Buffer = true;//(默认值就是true)启用缓冲区
 Response.Flush();//将缓冲区的内容立刻发送到客户端
 Response.Clear();//清空缓冲区
 Response.End();//终止响应,将缓冲区的东西发送到客户端
 Stream getContentStr = Response.OutputStream;//获得将要发送的流(流≈字节数组)

 

当每个页面都需要做检查是否登录(session中是否有值),可以建一个basePage类并且让这个类继承system.web.UI.Page。在basePage类中写一个Page_Init方法(就跟Page_Load方法一样),在该方法中去验证session中是否有值。

        //virtual 虚方法,便于子类重写
        public virtual void Page_Init(object sender, EventArgs e)
        {
            if (Session["User"] == null) {
                //do sth....                
            }
        }
Page_Init方法

 

页面整体缓存

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="AddStudent.WebForm1"  %>  下增加

<%@ OutputCache Duration="15" VaryByParam="*" %>    Duration表示页面缓存时间是15秒,VaryByParam后面的*表示当请求报文中的发生任何改动。VaryByParam="Id"___当url中的Id发生变化

 

       Session    :存放键值对;每个浏览器只要访问服务器就会被分配一个session,每个session都会有一个ID。sessionID会被放在Cookie中,当浏览器端的cookie被禁用,session也就没法用了。
       Cookie     : 存放在浏览器所在的机器上。
       Cache      : 局部缓存,拥有更好的性能。
       ViewState  : 实质上就是一个隐藏域,在同一个页面中存取值可以使用。
       Application: 只要应用程序启动就会被创建,任何地方都能被获取到。
C# 缓存对象之间的差异

 

            Cache["key"] = "vichin";
            Cache.Remove("key");
            Cache.Insert("key", DateTime.Now.ToString(), null, DateTime.Now.AddDays(3), TimeSpan.Zero);//设置绝对过期时间。3天后过期。
            Cache.Insert("key", DateTime.Now.ToString(), null, DateTime.MaxValue, new TimeSpan(0, 0, 10));//设置滑动过期时间10秒。(10秒内,若缓存没有被访问,则过期。否则缓存过期时间重新变成10秒)

            //依赖文件缓存。 
            string file = Request.MapPath("08a.txt");//依赖一个txt文本,当文本内的内容发生变化的时候,缓存过期。(页面菜单可以使用这个功能)
            Cache.Insert("key",DateTime.Now.ToString(),new CacheDependency(file));

            //依赖数据库缓存
            //   ……
Cache的使用

 System.Web.HttpRuntime.Cache

 


 

linq中的find()与where(),where每次都会去数据库执行,而find会去实体(缓存中)去找。

MVC能够快速的CURD是得益于实体在前后台的绑定。 前台可以直接取到实体中的值,从而生成页面。后台也可以将前台HTML标签中的name来映射到实体中,从而取到值。

 

//LinQ联合查询 masterList为武林高手集合,kongfuList为武功集合
            var result = from m in masterList
                         from k in kongfuList
                         where m.Kongfu == k.name && k.power > 90
                         select new { master=m,kongfu=k};

            //使用方法语法进行查询
            var result1 = masterList.SelectMany(m => kongfuList, (m, k) => new { master = m,kongfu = k}).Where(x => x.Power > 90 &&
                x.master.kongfu == x.kongfu.name);            
            //m => kongfuList表示将masterList和kongfuList进行联合查询,
            //SelectMany方法的第二个参数表示,将两个对象进行联合查询之后,组合成的一个新的结果。

            //使用join on 进行联合查询
            var result = from m in masterList
                         join k in kongfuList on m.kongfu equals k.name
                         select new { master = m, kongfu = k };
LinQ联合查询

排序 

orderby(p => p.age).thenby(p => p.times);

 


 


String 的特性

1、不可继承性(微软内部使用了sealed关键字)
2、不可变性
      string a = "vichin";在内存区域开辟一个空间,存放vichin这个固定字符串。将a变量指向这个空间
      string b = "james";在内存区域开辟一个空间,存"放james这个固定字符串。将b变量指向这个空间
      a = a + b;     开辟一块空间,存放a变量(vichin)与 b变量(james)相加后的值 这里并不是将原先a变量指向的内存空间内的值(vichin)替换成(vichinjames),
               而是重新开辟一块内存空间,用于存放"vichinjames"。之前用于存放vichin那个字符串的空间并不会被GC回收————字符串暂存池(驻留池)。
3、字符串暂存池(驻留池)
      接上————1、上面a变量重新指向了新的对象"vichinjames",老的对象"vichin"并没被GC回收,依然存留在内存空间当中(只有当程序完全结束的时候,这些对象才会消除)。
                   当一个程序内多次使用字符串相加操作之后,就会在内存中多次开辟内存空间,对内存产生大量不必要的消耗。                                                                                                                                                                       2、string a="vichin",想这样将一个固定的字符串赋值给a变量,a变量将会被存放在暂存池中。如果通过调用一个方法比如说string a=GetName();来获取的话,                                                                                                 那么a变量将不会被存放在暂存池中。

              

 

            Dictionary<string, int> Player = new Dictionary<string, int>();
            Player.Add("vichin", 8);
            Player.Add("james", 23);
            Player.Add("stephen", 30);

            for (int i = 0; i < Player.Count; i++)
            {
                var item = Player.ElementAt(i);
                string name = item.Key;
                int num = item.Value;


            }
            foreach (var item in Player)
            {
                string name = item.Key;
                int num = item.Value;
            }

            foreach (var item in Player.Keys)
            {
                int num = Player[item];
            }

            foreach (var item in Player.Values)
            {
                int i = 0;
                i = i + item;
            }
            foreach (KeyValuePair<string, int> item in Player)
            {

            }
遍历Dictionary

 

ToString()可空参数单独使用,同时可以加一个格式化参数,具体方式如下:
1. 取中文日期显示_年月 currentTime.ToString("y"); 格式:2007年1月
2. 取中文日期显示_月日 currentTime.ToString("m"); 格式:1月30日
3. 取日期显示_年月日 currentTime.ToString("d"); 格式:2007-1-30
4. 取日期显示_时分 currentTime.ToString("t"); 格式:15:35
5. Int32.Parse(变量) Int32.Parse("常量") 字符型转换 转为32位数字型
6. 变量.ToString() 字符型转换 转为字符串
   12345.ToString("n"); //生成 12,345.00
   12345.ToString("C"); //生成 ¥12,345.00
   12345.ToString("e"); //生成 1.234500e+004
   12345.ToString("f4"); //生成 12345.0000
   12345.ToString("x"); //生成 3039
7. 变量.ToString("yyyyMMdd") ; 格式:20070101
8.变量.ToString(".00") ; 格式:*.??
tostring()常用重载

 

posted @ 2017-08-18 11:30  水墨晨诗  阅读(584)  评论(4编辑  收藏  举报