zoukankan      html  css  js  c++  java
  • 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("你好"+"
    ");
                }
            }
    
           
        }
    //其他类的用法类似,有相应的文档
    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}	", evennum);
                //}
                //Console.ReadKey();
                //////////////////////////////////////////////////////////////////////////
                //采用匿名方法
                //List<int> evennumbers = list.FindAll(delegate (int num)
                //{
                //    return (num % 2 == 0);
                //});
                //foreach (int evennum in evennumbers)
                //{
                //    Console.WriteLine("{0}	", evennum);
                //}
    
                //////////////////////////////////////////////////////////////////////////
                //采用Lamada表达式
                List<int> evennumbers = list.FindAll(num=>(num%2)==0);
                //运行时被编译成了上述匿名方法
                foreach (int evennum in evennumbers)
                {
                    Console.WriteLine("{0}	", 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)接口可以继承,继承后如果一个类实现了该接口,则该接口继承的接口成员也需要被实现,同时接口也支持多种继承,若不同接口存在命名冲突,可以通过显式接口解决冲突。

      

  • 相关阅读:
    HTML DOM 06 节点关系
    HTML DOM 05 事件(三)
    HTML DOM 05 事件(二)
    HTML DOM 05 事件(一)
    html DOM 04 样式
    html DOM 03 节点的属性
    html DOM 02 获取节点
    html DOM 01 节点概念
    JavaScript 29 计时器
    JavaScript 28 弹出框
  • 原文地址:https://www.cnblogs.com/janghe/p/7445930.html
Copyright © 2011-2022 走看看