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

      

  • 相关阅读:
    APP上传问题集锦
    objectiveC【语法】修饰符 static extern const
    NSLog
    iOS开发之获取系统相册中的图片与视频(内带url转换)
    Re:iOS 开发中的争议(一、二)
    iOS静态库(.a 和framework)
    iOS 获取本地视频的缩略图
    iOS 查询数组中的对象
    IOS判断文件类型
    循环引用问题 -- dealloc方法不执行
  • 原文地址:https://www.cnblogs.com/janghe/p/7445930.html
Copyright © 2011-2022 走看看