C#中的特殊数据类型

一、c#中的特殊数据类型

C#中特殊数据类型有class类型、结构类型、数组类型、枚举类型、集合类型、委托类型、事件、Lambda表达式、接口类型。

1、class类型
1.1类定义
class Student : person//继承
{
    //默认构造函数,vs IDE中输入ator+tab两下可自动生成构造函数代码段
    public Student()
    {
        //给字段赋值等初始化操作
    }
    //自定义构造函数,b为可选参数
    public Student(int a, string b = 5)
    {
        //初始化操作
    }
    public Student(int a)//自定义构造函数
    {
        //初始化操作
    }
    //静态构造函数-安全的给静态字段赋值且只能被定义一个(采用普通构造函数每次实例化类对象时静态字段的值会被重置)
    static Student{aCuu=0.04}//不允许访问修饰符,不接受参数

//static关键字用来定义静态成员,这些成员只能通过类级别而不是对象引用调用。
//static关键字,静态字段由所有类实例共享
public static double aCuu = 0.04;
public string petName;//字段,最好定义成私有的以保护
public void Name(string name) { }---方法
 
 }
 
 //静态类-只包含静态成员,不能够使用new(分配新内存)关键字来创建类对象-适合做工具类
 static class Student { }

 

1.2访问修饰符

类型成员隐式私有的,而类是隐式内部的。

private、protected、protected internal访问修饰符可以应用到嵌套类型上,非嵌套类型只能用public internal修饰符定义。

public 可以从对象、派生类、外部其它程序集访问
private 定义类访问
protected 定义类及子类可以访问,外部类无法通过点操作符访问
internal 只能在当前程序集中访问
protected internal 在定义该项的程序集、类及派生类中可用
1.3 this 关键字

提供对当前类实例的访问。

串联构造函数,使类更容易维护和简明。

    class Motorcycle
    {
        public int driverIntensity;
        public string drivername;
        //构造函数
        public Motorcycle(){}
        public Motorcycle(int intensity) : this(intensity, "") { }            
        public Motorcycle(string name):this(0,name) { }
        //所有工作的主构造函数
        public Motorcycle(int intensity,string name)
        { 
            //操作
        }
    }
2、结构类型

结构类型可以看成是轻量级的类类型,但是不能像类一样继承

  struct point 
  {
        //字段
        public int x;
        //方法
        public void Increment()
        {
        }  
    }

    //创建结构变量
    point p1;
    p1.x = 5;//需要为每一个共有字段成员赋值
            point p2 = new point();
3、数组类型

一组相同类型的数据点:int[] myInt=new int[3]

int[] myInt=new int[3]{1,2,3}  #初始化

3.1 特殊数组
隐式数组 var a=new[]{1,2,3}
object数组 object[] myob=new[3]{1,"string",new DateTime(2017,8,28)}
多维数组 int[,] myArray=new int[6,6]
4、枚举类型

System.Enum类中包含有一些对枚举类型操作的方法

 enum Emptype:Byte
    {
        manager=12,//=0,可任意,可不连续
        student,
        teancher
    }

    Emptype ee = Emptype.manager;
    Enum.GetUnderlyingType(ee.GetType());//返回枚举类型值的数据类型
            Console.WriteLine(ee.ToString());//获取枚举名字
            Console.WriteLine((Byte)ee);//根据底层类型强制转换获取其数值

            Array enumData = Enum.GetValues(ee.GetType());//获取所有枚举值
    Console.WriteLine("this enum has {0} nums:", enumData.Length);
            Console.WriteLine("name{0};value{1}", enumData.GetValue(1));
 5、集合类型-数据容器

System.Collections与System.Collection.Generic命名空间

  简单数组通常是固定大小的,而集合类本身的尺寸是动态的,类似于python中的list类型,很多集合提供了更强的类型安全,进行了高度优化,可以以内存高效的方式处理所包含的数据。

  集合可划分为两大种类:非泛型集合和泛型集合

5.1泛型集合System.Collections常用类

 

ArrrayList 动态大小对象集合,对象按顺序列出 Ilist/Icollection/IEnumerable/ICloneable
BitArray 管理位值的简单数组,位值bool类型 ICollection/IEnumerable/ICloneable
Hashtable 表示键值对的集合 IDictionary/Icollection/IEnumerable/ICloneable
Queue FIFO队列 ICollection/IEnumerable/ICloneable
SortedList 键值对集合按键排序 IDictionary/Icollection/IEnumerable/ICloneable
Stack 后进先出 ICollection/IEnumerable/ICloneable

System.Collections中类所支持的关键接口

ICollection 为所有非泛型集合定义基本特性(大小、枚举、线程安全)
ICloneable 允许实现它的对象向调用者返回它的副本
IDictionary 非泛型集合使用键值对表示其内容
IEnumerable 返回实现了IEnumerable接口的对象
IEnumerator 允许子类型以foreach形式迭代
IList 为顺序列表中的对象提供添加、移除和索引项的行为

示例代码:

class Program
    {
        static void Main(string[] args)
        {
            ArrayList list = new ArrayList();
            //集合:很多数据的一个集合
            //数组:长度不可变、类型单一
            list.Add(true);
            list.Add(1);
            list.Add(2);
            list.Add("张三");
            Person person = new Person();
            list.Add(person);
            list.Add(new int[] { 1, 2, 3 });
            list.AddRange(list);
            list.AddRange(new int[] { 234, 23432 });//此种方法可以直接输出
            for(int i=0; i<list.Count; i++)
            {
                if(list[i] is Person )
                {
                    ((Person)list[i]).SayKello();
                }
                else if(list[i] is int[])
                {
                     for(int j=0;j<((int[])list[i]).Length;j++)
                    {
                        Console.WriteLine(((int[])list[i])[j]);
                    }
                }   //麻烦
                else
                {
                    Console.WriteLine(list[i]);
                }
                
            }
            Console.ReadKey();   
            //List元素打印出来的是所在类对应的命名空间
        }

        class Person
        {
            public void SayKello()
            {
                Console.Write("你好"+"\r\n");
            }
        }

       
    }
//其他类的用法类似,有相应的文档
HashTable示例:
  static void Main(string[] args)
        {

            //键值对集合类似于字典,根据键去找值,就像根据拼音去找汉字
            Hashtable ht = new Hashtable();
            ht.Add(1,"张三");
            ht.Add(2,"小王");
            ht.Add(false,"错误的");
            for (int i = 0; i < ht.Count; i++)
            {
                object a = ht[i];
                Console.WriteLine(a);
            }
            //不能全部显示(0和false)
            Console.ReadKey();
            Console.WriteLine(ht[false]);

            //也可以采用foreach循环遍历
            foreach (var item in ht.Keys)   
            {
                //C#是一门强类型语言:代码中每一个变量类型必须有明确的定义
                //int n = 15;
                //string ste = "sfdd";
                //bool n5 = true;
                //double n6 = 230.23;
                //Console.WriteLine(n.GetType());
                //Console.WriteLine(ste.GetType());
                //Console.WriteLine(n5.GetType());
                //Console.WriteLine(n6.GetType());
                //Console.ReadKey();

                //根据值推断出类型
                //var n = 15;
                //var ste = "sfdd";
                //var n5 = true;
                //var n6 = 230.23;

                //Console.WriteLine(n.GetType());
                //Console.WriteLine(ste.GetType());
                //Console.WriteLine(n5.GetType());
                //Console.WriteLine(n6.GetType());
                //Console.ReadKey();
                //var input; 声明var变量的时候必需给它赋值
                //input = "人民";
                Console.WriteLine(ht[item]);
            }
            Console.ReadKey();


        }
View Code
5.2非泛型集合

  相比较于泛型集合,非泛型集合更为常用,经典的泛型集合常常存在如下问题:

1)频繁的装箱拆箱操作,当数据量过大时会降低程序效率:

  .NET包含一个特殊的Object类,可以接受任意的数据类型的值,当所传递或所赋值的类型不是一个特定的数据类型时,object类就提供了一种传递参数和赋值的通用方法。赋给object的值必须作为引用类型,并存放砸托管堆中,简言之装箱就是值类型转换为引用类型;拆箱就是引用类型转换为值类型。

  值类型:包括原类型(Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、Double、Bool、Decimal)、枚举 (enum) 、结构 (struct)。

  引用类型:包括类、数组、接口、委托、字符串等

  一下特殊情况需要注意:

隐式转换总会成功的情况 显式引用转换可能会抛出异常的情况
从派生类到基类 从基类到派生类
从派生接口到基接口 从接口到接口(基接口到派生接口或者俩接口没有关系)
从类到接口(该类实现了接口) 从接口到类(该类实现了该接口或该类未封闭)
从Null到任何类 从类到接口(该类未实现该接口且该类未封闭)

 

 class Program
    {
        int a = 3;
        object ob = a;//装箱操作
        int b = (int)ob;//拆箱操作
    }

 2)类型安全问题,所有的类型都可以转换成object类,在特定的情况下存在类型安全问题。

 5.3泛型集合

只有类、结构、接口和委托可以使用泛型,枚举类型不可以。

1)System.Collection.Generic命名空间

 

 2)初始化语法

 class Point
        {
            int x;
            int y;
            public Point(int x, int y)
            {
                this.x = x;
                this.y = y;
            }

        }
class Program
    {
        static void Main(string[] args)
        {
            List<Point> myOfpoint = new List<Point>
            {
                new Point(1,2),
                new Point(3,4)
            };
        }
    }

3)List<T>类

常见用法见:http://www.cnblogs.com/AdaLoong/p/5528917.html

4)Stack<T>类---后进先出

包含Push和Pop方法,可以向栈中压入数据或弹出数据,在观察栈时得到的永远是栈顶对象,可以通过调用peek()来显示。

http://www.cnblogs.com/deom/p/5349317.html

5)Queue<T>类---先进先出

http://www.cnblogs.com/jiahuafu/archive/2013/01/05/2845640.html

Dequeue()---移除并返回开始出的对象;

Enqueue()---在末未添加一对象;

peek()---返回开始出的对象但是不移除。

6)SortedSet<T>类---自动排序

必须通知SortedSet<T>类按照何种方式排序,可以向其构造函数传递一个实现了IComparer<T>泛型接口的参数,比如一个实现了该泛型接口的类。

http://blog.sina.com.cn/s/blog_621e24e20100zqmq.html

 

class sortByage:IComparer<Person>
    {
        public int Compare(Person firstperson,Person secondperson)
        {
            if (firstperson.age > secondperson.age)
                return 1;
            if (firstperson.age < secondperson.age)
                return -1;
            else
                return 0;
        }
    }
 class Person
    {
        string firstname;
        string lastname;
        public int age;      
        public Person(string firstname,string lastname,int age)
        {
            this.firstname = firstname;
            this.lastname = lastname;
            this.age = age;
        }
    }
static void Main(string[] args)
        {
            SortedSet<Person> mysortedOfperson = new SortedSet<Person>(new sortByage())
            {
              new Person("wangming","zhang",112),
              new Person("xiaogang","wang",13),
              new Person("xiaohong","li",56)
            };
            //按照年龄排序
            foreach (Person p in mysortedOfperson)
            {
                Console.WriteLine(p.age);
            }
            Console.ReadKey();
        }

 7)System.Collections.ObjectModel命名空间

该命名空间也是以泛型为核心

两个比较有用的类

ObservableCollection<T> 表示能在添加、移除项或者刷新整个列表时提供通知的动态数据集合
ReadOnltObservableCollection<T> 表示ObservableCollection<T>的只读版本

  ObservableCollection<T>与List<T>具有相同的核心接口,不同的是ObservableCollection<T>实现了名为CollectionChanged的事件,该事件在添加、移除项或者刷新整个列表时触发。

  CollectionChanged定义为委托,该委托可以调用一类方法(第一个参数为object,第二个参数为NotifyCollectionChangedEventArgs)。

  

class Program
    {
        static void Main(string[] args)
        {
            ObservableCollection<Person> mysortedOfperson = new ObservableCollection<Person>()
            {
              new Person("wangming","zhang",112),
              new Person("xiaogang","wang",13),
              new Person("xiaohong","li",56)
            };
            //按照年龄排序
            //绑定collentionchanged事件
            mysortedOfperson.CollectionChanged += people_collentionchanged;
            mysortedOfperson.Add(new Person("jfoda", "ad", 12));
            Console.ReadKey();
            
        }
        static void people_collentionchanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            //触发事件的行为是什么
            Console.WriteLine("Action for this event:{0}", e.Action);
            if(e.Action==System.Collections.Specialized.NotifyCollectionChangedAction.Add)
            {
                Console.WriteLine("here are the new item:");
                foreach (Person p in e.NewItems)
                {
                    Console.WriteLine(p.ToString());
                }
            }
        }

    }
    class Person
    {
        string firstname;
        string lastname;
        public int age;      
        public Person(string firstname,string lastname,int age)
        {
            this.firstname = firstname;
            this.lastname = lastname;
            this.age = age;
        }
    }
6、委托类型delegate

委托类型用来定义和响应应用程序中的回调,使用回调程序员可以使用一个函数返回报告给程序中的另一个函数,使用这种方法,windows开发者可以可以处理按钮单击、鼠标移动、菜单选择以及内存中两个实体的双向通信。本质上委托是个类型安全的对象,它指向一个以后会被调用的方法(或者多个方法),可以不用手工创建一个thread对象去条用其它thread上的方法,委托类型有三个重要的信息:

1)它所调用的方法和名称

2)该方法的参数(可选)

3)该方法的返回值类型(可选)

6.1、委托类型的定义

public delegate int BinaryOp(int x,int y)

使用delegate关键字,就间接创建了一个类,这个类是“MulticastDelegate”,下表显示了所有委托对象都有的核心成员。

例1:

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

namespace 委托简例
{
    public delegate int BinaryOp(int x, int y);
    //创建一个包含委托指向方法的类
    public class SimpleMath
    {
        public int Add(int x, int y)
        {
            return x + y;
        }
    }
    class Program
    {
        //显示委托对象所维护的方法名称及对应的类名称
        static void DisplayDelegateInfo(Delegate delObj)
        {
            //输出委托调用列表中每个成员的名称
            foreach (Delegate d in delObj.GetInvocationList())
            {
                Console.WriteLine("Method name:{0}", d.Method);
                Console.WriteLine("Type name:{0}", d.Target);
            }
            Console.ReadKey();
        }
        static void Main(string[] args)
        {
            //实例化一个委托对象
            BinaryOp bp = new BinaryOp(new SimpleMath().Add);//指向的是非静态方法要生成实例
            //BinaryOp bp = new BinaryOp(SimpleMath.Add);//指向的是静态方法则不需要,只需给出内存地址即可
            Console.WriteLine("10+10={0}", bp(10, 10));
            Console.ReadKey();
            DisplayDelegateInfo(bp);
        }
    }
}
例2
//声明委托
    public delegate void Mydel();
    public delegate void Mydel2(int num1, int num2);
    public delegate string Mydel3(string s);
    //声明委托用于演示匿名方法
    public delegate string ProcessString(string S);
    class Program
    {
        static void Main(string[] args)
        {          
            TestDel t = new TestDel();
            #region 简单实例化委托与调用委托
            Console.WriteLine("------以下是简单使用委托演示----");
            t.MyMethod();

            //实例化委托,用一个方法实例化
            //该方法签名要与委托签名一致
            Mydel del0 = new Mydel(t.MyMethod);
            //调用委托
            del0();
            //另一种实例化方法
            Mydel del1 = t.MyMethod;
            del1();

            //用静态方法进行实例化
            del1 = TestDel.MyStaticMethod;
            del1();
            //以下代码效果相同
            //类TestDel中重载了多种MyMethod方法,委托自动识别一致参数类型的方法
            Mydel2 del2 = new Mydel2(t.MyMethod);
            del2(10,20);
            Mydel2 del121 = t.MyMethod;
            del121(10, 20);
            Mydel3 del3 = new Mydel3(t.MyMethod);
            del3("adfa");
            #endregion

            #region 匿名实例化weit
            Console.WriteLine("-----以下是匿名调用委托--");
            //用匿名方法实例化委托,不需函数名,直接就是参数+函数体
            ProcessString p = delegate(string inputString)
              {
                  return inputString.ToUpper();
              };
             //通过委托调用匿名方法
            Console.WriteLine(p("wefewe"));
            #endregion
    
            #region 委托多播演示
            Console.WriteLine("---------以下是多播演示--------");
            Mydel mydel1 = t.MyMethod;
            Mydel mydel2 = t.MyMethod2;
            Mydel mydel3 = TestDel.MyMethod3;
            //委托类型必须一致才能相加
            Mydel allmydel = mydel1 + mydel2 + mydel3;
            allmydel();
            allmydel -= mydel3;
            allmydel();
            #endregion

            #region 委托作为参数演示
            Console.WriteLine("-------以下委托作为参数演示--------");
            Mydel3 paraMydel3 = t.MyMethod;
            TestDel.MyParamMethod("aaa", paraMydel3);
            #endregion


            #region 委托作为返回值
            Console.WriteLine("----以下委托作为返回值演示-----");
            //returnMydel指向ReturnMyMethod的返回值
            Mydel3 returnMydel = t.ReturnMyMethod();
            //returnMydel1指向t.MyMethod
            Mydel3 returnMydel1 = t.MyMethod;
            Console.WriteLine(returnMydel("sssssss"));
            #endregion          

        }

    }
    public class TestDel
    {
        #region 普通方法
        public static void MyStaticMethod()
        {
            Console.WriteLine("My Static Method");
        }
        public void MyMethod()
        {
            Console.WriteLine("MyMethod");
        }
        public void MyMethod2()
        {
            Console.WriteLine("My Method 22222222222");
        }
        public static void MyMethod3()
        {
            Console.WriteLine("My Method 3333333333333");
        }
        public void MyMethod(int num1, int num2)
        {
            Console.WriteLine(num1 + num2);
        }
        public string MyMethod(string s)
        {
            return s.ToUpper();
        }
        #endregion
        /// <summary>
        /// 委托作为方法参数
        /// </summary>
        /// <param name="s"></param>
        /// <param name="del3"></param>
        public static void MyParamMethod(string s, Mydel3 del3)
        {
            Console.WriteLine(del3(s));
        }
        /// <summary>
        /// 委托作为返回值
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public Mydel3 ReturnMyMethod()
        {
            ///返回符合委托规范的方法
            return MyMethod;
        }

    }
View Code

 

6.2使用委托发送对象通知状态

类似于通过回调函数返回状态信息

namespace 委托通知
{
    //使用委托来定义car类,他可以通知外部实体当前引擎状态
    /// <summary>
    /// (1)定义将通知发送给调用者的委托类型
    /// (2)声明car类中每个委托类型的成员变量
    /// (3)在car上创建副主函数使得调用者能指定由委托成员变量保存的方法
    /// (4)修改Accelerate()方法以在适当的情形下调用委托的调用列表
    /// </summary>
    public class Car
    {
        //内部状态数据
        public int CurentSpeed;
        public int MaxSpeed;
        public string name;
        //汽车能不能用
        private bool carIsdead;
        //类构造函数
        public Car() { }
        public Car(string name,int currentspeed,int maxspeed=100)
        {
            this.name = name;
            this.CurentSpeed = currentspeed;
            this.MaxSpeed = maxspeed;
        }
        //定义委托类型
        public delegate void CarEngineHandler(string msdForCar);
        //定义每个委托类型的成员变量
        private CarEngineHandler listOfhandlers;
        //向调用者添加注册函数
        public void RegisterWithCarEngine(CarEngineHandler methodTocall)
        {
            if (listOfhandlers == null)
                listOfhandlers = methodTocall;
            else
                listOfhandlers += methodTocall;//支持多路广播
        }
        //实现Accelerate()方法
        public void Accelerate(int delta)
        {
            if(carIsdead)
            {
                if(listOfhandlers!=null)
                {
                    listOfhandlers("sorry,this car is dead");
                }
            }
            else
            {
                CurentSpeed += delta;
                //不能超过最大速度
                if(5==(MaxSpeed-CurentSpeed) && listOfhandlers != null)
                {
                    listOfhandlers("this speed is nearly to the maxspeed");
                }
                if (CurentSpeed > MaxSpeed)
                {
                    carIsdead = true;
                }
                else
                    Console.WriteLine("current speed:{0}", CurentSpeed);
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //首先创建一个car对象
            Car mycar = new Car("xiaowang",10);
            //现在告诉汽车他想要向我们发送信息是应该调用哪个方法
            mycar.RegisterWithCarEngine(new Car.CarEngineHandler(OnCarEngineEvent));
            //方法组转换语句---传递与委托类型一致的函数
            //mycar.RegisterWithCarEngine(CallMeHere);
            //加速,触发事件
            Console.WriteLine("*******speed up********");
            for(int i=0;i<6;i++)
            {
                mycar.Accelerate(20);
                Console.ReadKey();
            }
            //要传入事件的方法
        }
        public static void OnCarEngineEvent(string msg)
        {
            Console.WriteLine("feedback information:{0}", msg);
        }
        static void CallMeHere(string msg)
        {
            Console.WriteLine("feedback information:{0}", msg);
        }
    }
}
 6.2实现多路广播---见6.1
6.3泛型委托

泛型参数

      public delegate void MyDelegate<T>(T mycan);-------对应一类函数

泛型Action<>和Func<>委托------框架内置的委托

泛型Action:可以指向多至16个参数并返回void的方法,需要制定各个参数的具体类型。

Func<>委托:可以指向多至16个参数并且具有自定义返回值。

Func<int,int,int> functarget=new Func<int,int,int>(Add);

Add中本有两个参数,Func<int,int,int>最后一个参数是返回值。

7、事件

event关键字在变已处理的时候,它会自动的提供注册和注销方法以及任何必要的委托类型成员变量,这些成员变量是私有的,不能从出发事件的对象访问。

定义事件:

1)定义委托类型----事件触发时要调用的方法;

2)用相关委托声明这个事件----使用event关键字。

namespace 委托通知
{
    //使用委托来定义car类,他可以通知外部实体当前引擎状态
    /// <summary>
    /// (1)定义将通知发送给调用者的委托类型
    /// (2)声明car类中每个委托类型的成员变量
    /// (3)在car上创建副主函数使得调用者能指定由委托成员变量保存的方法
    /// (4)修改Accelerate()方法以在适当的情形下调用委托的调用列表
    /// </summary>
 namespace 委托通知
{
    //使用委托来定义car类,他可以通知外部实体当前引擎状态
    /// <summary>
    /// (1)定义将通知发送给调用者的委托类型
    /// (2)声明car类中每个委托类型的成员变量
    /// (3)在car上创建副主函数使得调用者能指定由委托成员变量保存的方法
    /// (4)修改Accelerate()方法以在适当的情形下调用委托的调用列表
    /// </summary>
    public class Car
    {
        //内部状态数据
        public int CurentSpeed;
        public int MaxSpeed;
        public string name;
        //汽车能不能用
        private bool carIsdead;
        //类构造函数
        public Car() { }
        public Car(string name, int currentspeed, int maxspeed = 100)
        {
            this.name = name;
            this.CurentSpeed = currentspeed;
            this.MaxSpeed = maxspeed;
        }
        //定义委托类型
        public delegate void CarEngineHandler(string msdForCar);
        //定义每个委托类型的成员变量
        private CarEngineHandler listOfhandlers;
        //向调用者添加注册函数
        public void RegisterWithCarEngine(CarEngineHandler methodTocall)
        {
            if (listOfhandlers == null)
                listOfhandlers = methodTocall;
            else
                listOfhandlers += methodTocall;//支持多路广播
        }
        //实现Accelerate()方法
        public void Accelerate(int delta)
        {
            if (carIsdead)
            {
                if (listOfhandlers != null)
                {
                    listOfhandlers("sorry,this car is dead");
                }
            }
            else
            {
                CurentSpeed += delta;
                //不能超过最大速度
                if (5 == (MaxSpeed - CurentSpeed) && listOfhandlers != null)
                {
                    listOfhandlers("this speed is nearly to the maxspeed");
                }
                if (CurentSpeed > MaxSpeed)
                {
                    carIsdead = true;
                }
                else
                    Console.WriteLine("current speed:{0}", CurentSpeed);
            }
        }
    }
    public class newCar
    {
        //内部状态数据
        public int CurentSpeed;
        public int MaxSpeed;
        public string name;
        //汽车能不能用
        private bool carIsdead;
        //类构造函数
        public newCar() { }
        public newCar(string name, int currentspeed, int maxspeed = 100)
        {
            this.name = name;
            this.CurentSpeed = currentspeed;
            this.MaxSpeed = maxspeed;
        }
        //定义委托用来与car的时间协作
        public delegate void CarEngineNewHandles(string msg);
        //汽车可以发送的事件
        public event CarEngineNewHandles Exploded;
        public event CarEngineNewHandles AbouttoBlow;

        public void NewAccelerate(int delta)
        {
            if (carIsdead)
            {
                if (Exploded != null)
                {
                    Exploded("sorry,this car is dead");
                }
            }
            else
            {
                CurentSpeed += delta;
                //不能超过最大速度
                if (5 == (MaxSpeed - CurentSpeed) && AbouttoBlow != null)
                {
                    AbouttoBlow("this speed is nearly to the maxspeed");
                }
                if (CurentSpeed > MaxSpeed)
                {
                    carIsdead = true;
                }
                else
                    Console.WriteLine("current speed:{0}", CurentSpeed);
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //////////////////////////////////////////////////////////////////////////使用委托回调
            //首先创建一个car对象
            Car mycar = new Car("xiaowang", 10);
            //现在告诉汽车他想要向我们发送信息是应该调用哪个方法
            mycar.RegisterWithCarEngine(new Car.CarEngineHandler(OnCarEngineEvent));
            //方法组转换的---传递与委托类型一致的函数
            //mycar.RegisterWithCarEngine(CallMeHere);
            //加速,触发事件
            Console.WriteLine("*******speed up********");
            for (int i = 0; i < 6; i++)
            {
                mycar.Accelerate(20);
                Console.ReadKey();
            }

            ////////////////////////////////////////////////////////////////////////// 使用事件回调

            //调用者监听传入的事件
            ///先要使用+=h和-=注册和删除事件
            newCar c1 = new newCar("wangming", 30);
            //注册事件处理程序
            c1.AbouttoBlow += new newCar.CarEngineNewHandles(CarIsAboutToBlow);
            c1.AbouttoBlow += new newCar.CarEngineNewHandles(CarIsAmostAboutToBlow);


            newCar.CarEngineNewHandles d = new newCar.CarEngineNewHandles(OnCarEngineEvent);
            c1.Exploded += d;

            for (int i = 0; i < 6; i++)
            {
                c1.NewAccelerate(30);
                Console.ReadLine();
            }

            ///使用方法组转换简化
            newCar c2 = new newCar("wangming", 30);
            //注册事件处理程序
            c2.AbouttoBlow += CarIsAboutToBlow;
            c2.AbouttoBlow += CarIsAmostAboutToBlow;
            newCar.CarEngineNewHandles d2 = new newCar.CarEngineNewHandles(OnCarEngineEvent);
            c2.Exploded += d2;

        }

        
        public static void OnCarEngineEvent(string msg)
        {
            Console.WriteLine("feedback information:{0}", msg);
        }
        public static void CarIsAboutToBlow(string msg)
        {
            Console.WriteLine("car is about to blow");
        }
        public static void CarIsAmostAboutToBlow(string msg)
        {
            Console.WriteLine("car is about to blow");
        }
    }


}

    public class newCar
    {
        //内部状态数据
        public int CurentSpeed;
        public int MaxSpeed;
        public string name;
        //汽车能不能用
        private bool carIsdead;
        //类构造函数
        public newCar() { }
        public newCar(string name, int currentspeed, int maxspeed = 100)
        {
            this.name = name;
            this.CurentSpeed = currentspeed;
            this.MaxSpeed = maxspeed;
        }
        //定义委托用来与car的时间协作
        public delegate void CarEngineNewHandles(string msg);
        //汽车可以发送的事件
        public event CarEngineNewHandles Exploded;
        public event CarEngineNewHandles AbouttoBlow;

        public void NewAccelerate(int delta)
        {
            if (carIsdead)
            {
                if (Exploded != null)
                {
                    Exploded("sorry,this car is dead");
                }
            }
            else
            {
                CurentSpeed += delta;
                //不能超过最大速度
                if (5 == (MaxSpeed - CurentSpeed) && AbouttoBlow != null)
                {
                    AbouttoBlow("this speed is nearly to the maxspeed");
                }
                if (CurentSpeed > MaxSpeed)
                {
                    carIsdead = true;
                }
                else
                    Console.WriteLine("current speed:{0}", CurentSpeed);
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //////////////////////////////////////////////////////////////////////////使用委托回调
            //首先创建一个car对象
            Car mycar = new Car("xiaowang", 10);
            //现在告诉汽车他想要向我们发送信息是应该调用哪个方法
            mycar.RegisterWithCarEngine(new Car.CarEngineHandler(OnCarEngineEvent));
            //方法组转换的---传递与委托类型一致的函数
            //mycar.RegisterWithCarEngine(CallMeHere);
            //加速,触发事件
            Console.WriteLine("*******speed up********");
            for (int i = 0; i < 6; i++)
            {
                mycar.Accelerate(20);
                Console.ReadKey();
            }

            ////////////////////////////////////////////////////////////////////////// 使用事件回调

            //调用者监听传入的事件
            ///先要使用+=h和-=注册和删除事件
            newCar c1 = new newCar("wangming", 30);
            //注册事件处理程序
            c1.AbouttoBlow += new newCar.CarEngineNewHandles(CarIsAboutToBlow);
            c1.AbouttoBlow += new newCar.CarEngineNewHandles(CarIsAmostAboutToBlow);


            newCar.CarEngineNewHandles d = new newCar.CarEngineNewHandles(OnCarEngineEvent);
            c1.Exploded += d;

            for (int i = 0; i < 6; i++)
            {
                c1.NewAccelerate(30);
                Console.ReadLine();
            }

            ///使用方法组转换简化
            newCar c2 = new newCar("wangming", 30);
            //注册事件处理程序
            c2.AbouttoBlow += CarIsAboutToBlow;
            c2.AbouttoBlow += CarIsAmostAboutToBlow;
            newCar.CarEngineNewHandles d2 = new newCar.CarEngineNewHandles(OnCarEngineEvent);
            c2.Exploded += d2;

        }

        
        public static void OnCarEngineEvent(string msg)
        {
            Console.WriteLine("feedback information:{0}", msg);
        }
        public static void CarIsAboutToBlow(string msg)
        {
            Console.WriteLine("car is about to blow");
        }
        public static void CarIsAmostAboutToBlow(string msg)
        {
            Console.WriteLine("car is about to blow");
        }
    }

}
View Code

 从上面的例子也可以看出,手工定义一个委托对象调用的方法显的有点繁琐,不会很受欢迎,可以在实践注册时之间将一个委托与一段代码相关联-----------匿名方法。

示例代码入下:

            //注册事件处理程序作为匿名方法
            c3.AbouttoBlow += delegate (string msg)
            {
                Console.WriteLine("匿名委托返回消息{0}", msg);
                Console.ReadKey();
            };
            c3.Exploded += delegate (string msg)
            {
                Console.WriteLine("feedback information:{0}", msg);
                Console.ReadLine();
            };
            for (int i = 0; i < 6; i++)
            {
                c3.NewAccelerate(5);   
            }
8、Lambda表达式

lambda表达式本质上是用更简单的方法写匿名方法,首先定义一个参数列表,"=>"标记紧随其后,然后就是处理这些参数的语句。

ArgumentsToProcess=>StatementsToProcessThem;参数类型可以是显式的也可以是隐式的。

namespace Lambda表达式
{
    class Program
    {
        static void Main(string[] args)
        {
            TraditionalDelegateSyntax();
        }

        static void TraditionalDelegateSyntax()
        {
            //创建整数列表
            List<int> list = new List<int>();
            list.AddRange(new int[] { 20, 1, 4, 8, 444, 8 });

            ////使用传统委托方法调用FindAll()
            //Predicate<int> callback = new Predicate<int>(IsEvenNumber);
            //List<int> evennumbers = list.FindAll(callback);
            //foreach (int evennum in evennumbers)
            //{
            //    Console.WriteLine("{0}\t", evennum);
            //}
            //Console.ReadKey();
            //////////////////////////////////////////////////////////////////////////
            //采用匿名方法
            //List<int> evennumbers = list.FindAll(delegate (int num)
            //{
            //    return (num % 2 == 0);
            //});
            //foreach (int evennum in evennumbers)
            //{
            //    Console.WriteLine("{0}\t", evennum);
            //}

            //////////////////////////////////////////////////////////////////////////
            //采用Lamada表达式
            List<int> evennumbers = list.FindAll(num=>(num%2)==0);
            //运行时被编译成了上述匿名方法
            foreach (int evennum in evennumbers)
            {
                Console.WriteLine("{0}\t", evennum);
            }
            Console.ReadKey();

        }
        static bool IsEvenNumber(int num)
        {
            //这是个偶数
            return (num % 2 == 0);
        }
    }
}
9、接口

 接口是一组抽象成员的命名集合,由接口定义的某个特定成员依赖于它所模拟的确切行为。.NET基础库中提供了几百个预定义的接口类型,由各种类和结构实现。 与抽象类不同,接口只能包含抽象成员,由于C#中类不支持多重继承,一个父类定义的抽象成员只能被其派生类继承,但是大型系统中开发除了Object之外没有公共父类的多个层次结构很普遍,这样就不能配置多层次结构支持相同的多态接口,接口类型解决了这一问题,它可以被任何层次结构。任何命名空间或任何程序集中的任何类或结构来实现,这样接口就有了较高的多态性。

1)不能向类和结构一样分配类型:

Ipointy p=new Ipointy()

2)实现接口是个要"要么全要要么全部不要”的命题,即支持类型无法选择实现哪些成员。

    interface IPoint
    {
        //接口定义
        //1)不指定访问修饰符(默认隐式共有、抽象)
        //2)不能实现
       // byte GetNumofPoint();

        //只读属性
        byte Points{ get; }

    }
    //实现接口时要么全要,要么全不要
    class Triangle:Object,IPoint
    {   //...
        public byte Points
        {
            get { return 3; }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //在对象级别调用接口成员
            Triangle triangle = new Triangle();
            Console.WriteLine(triangle.Points);
            Console.ReadKey();
        }
    }
9.1怎样判定一个类型是否支持一个指定接口

1)使用显式强制转换。

 static void Main(string[] args)
        {
            //在对象级别调用接口成员
            Triangle triangle = new Triangle();
            try
            {
                IPoint point = null;
                point = (IPoint)triangle;
                Console.WriteLine(triangle.Points);
                Console.ReadKey();
            }
            catch (InvalidCastException e)
            {
                Console.WriteLine(e.Message);
            }
        }

2)as关键字

 IPoint point = null;
            point = triangle as IPoint;

3)is关键字

            //在对象级别调用接口成员
            Triangle triangle = new Triangle();
            try
            {

                if (triangle is IPoint)
                {
                    Console.WriteLine(triangle.Points);
                    Console.ReadKey();
                }
            }
            catch (InvalidCastException e)
            {
                Console.WriteLine(e.Message);
            }
9.2接口作为参数
 interface IPoint
    {
        //接口定义
        //1)不指定访问修饰符(默认隐式共有、抽象)
        //2)不能实现
        string GetNumofName();

        //只读属性
        //byte Points{ get; }

    }
    //实现接口时要么全要,要么全不要
    class Triangle : Object, IPoint
    {   //...
        public string GetNumofName()
        {
            return "i am Triangle ";
        }
    }
    class Rect : Object, IPoint
    {   //...
        public string GetNumofName()
        {
            return "i am Rect";
        }
    }
    class Program
    {
        static public string sayname(IPoint p)
        {
            return p.GetNumofName();
        }
        static void Main(string[] args)
        {
            //在对象级别调用接口成员
            //Triangle triangle = new Triangle();
            //try
            //{

            //    if (triangle is IPoint)
            //    {
            //        Console.WriteLine(triangle.Points);
            //        Console.ReadKey();
            //    }
            //}
            //catch (InvalidCastException e)
            //{
            //    Console.WriteLine(e.Message);
            //}

            object[] obj = { new Triangle(), new Rect() };
            for (int i = 0; i < obj.Length; i++)
            {
                if (obj[i] is IPoint)
                {
                    IPoint p = (IPoint)obj[i];
                    Console.WriteLine(sayname(p));
                }
            }
            Console.ReadKey();

        }
    }
View Code

类似的通过as/is关键字的使用,接口也可以作为返回值。

9.3接口数组

接口数组可以包含实现了该接口的任何类或者结构,不论相关不相关。

IPoint[]={new triangle(),new Tree(),new Rect()}

 9.4接口的层次结构

1)接口可以继承,继承后如果一个类实现了该接口,则该接口继承的接口成员也需要被实现,同时接口也支持多种继承,若不同接口存在命名冲突,可以通过显式接口解决冲突。

 

  

 

posted @ 2017-08-28 21:41  心灵智者  阅读(924)  评论(0编辑  收藏  举报