黑马程序员_C#面向对象知识总结3

---------------------- Windows Phone 7手机开发.Net培训、期待与您交流! ----------------------


委托

委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,


这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

委托可以认为是包含具有相同签名和返回值的有序方法列表,当委托被调用时,它调用列表中的每个方法


委托类型声明以delegate关键词开头,没有方法主体

委托声明方法
delegate void MyDel(int x);


例:声明没有参数和返回值的委托


    class Program
    {
        static void Main(string[] args)
        {
            //没有参数和返回值
            Test t = new Test();
            MyDel MD = t.print1;
            MD += Test.print2;
            MD += t.print1;
            MD += Test.print2;
            if (null != MD)
            {
                MD();
            }
            else
            {
                Console.WriteLine("delegate is empty");
            }
            Console.ReadKey();
        }
    }
    delegate void MyDel();  //没有参数和返回值
    class Test
    {
        public void print1()
        {
            Console.WriteLine("1231");
        }
        public static void print2()
        {
            Console.WriteLine("4564");
        }
    }


声明有返回值无参数的委托


    class Program
    {
        static void Main(string[] args)
        {
            //声明有返回值的委托
            MyClass mc= new MyClass();
            MyD mDel = mc.Add2;
            mDel += mc.Add3;
            mDel += mc.Add2;
            Console.WriteLine(mDel());
            Console.ReadKey();
        }
    }
    delegate int MyD();   //声明有返回值的委托
    //如果委托有返回值并且在调用列表中有一个以上的方法,会发生下面的情况:
    //    调用列表中最后一个方法的返回值就是委托调用的返回值
    //    调用列表中所有其他方法的返回值都会被忽略
    class MyClass
    {
        int i = 5;
        public int Add2()
        {
            i += 2;
            return i;
        }
        public int Add3()
        {
            i += 3;
            return i;
        }
    }


带引用参数的委托


    class Program
    {
        static void Main(string[] args)
        {
            //调用带引用参数的委托
            Class cl = new Class();
            Del de = cl.A;
            de += cl.B;
            de += cl.A;
            int x = 5;  //引用参数的值会在调用间发生改变
            de(ref x);
            Console.WriteLine(x);
            Console.ReadKey();
        }
    }
    delegate void Del(ref int x); //调用带引用参数的委托
    //如果委托有引用参数,参数值会根据调用列表中的一个或多个方法的返回值而改变
    //在调用委托列表中的下一个参数时,参数的新值(不是初始值)会传给下一个方法
    class Class
    {
        public void A(ref int x) { x += 2; }
        public void B(ref int x) { x += 3; }
    }


Lambda表达式


如果方法只会被使用一次,没有必要创建独立具名方法。匿名方法允许我们避免使用独立的具名方法,匿名方法是在初始化委托时内联声明的方法

        delegate int OtherDel(int i);
        public void Ni()
        {
            //OtherDel odel = Add20;

            //匿名方法转换为lambda表达式
            OtherDel odel = delegate(int x) { return x += 20; };  //使用匿名方法,省去了Add20方法
            //    删除delegate关键字
            //    在参数列表和匿名方法主体之间放lambda运算符 => 。
            OtherDel le1 = (int x) => { return x += 20; };  //表达式
            //编译器还可以从委托的声明中知道委托参数的类型,因此lambda表达式允许我们省略类型参数
            //    带有类型的参数列表称为显式类型
            //    省略类型和参数列表称为隐式类型
            OtherDel le2 =     (x) => { return x += 20; };
            //如果只有一个隐式类型参数,可以省略周围的圆括号
            OtherDel le3 =      x  => { return x += 20; };
            //lambda表达式允许表达式的主体是语句块或表达式,如果语句块包含了一个返回语句,可以将语句块替换为return关键字后的表达式
            OtherDel le4 =      x  =>          x += 20   ;
            Console.WriteLine("{0}  {1}  {2}  {3}  {4}",odel(5),le1(6),le2(7),le3(8),le4(8));
        }


事件


事件就好像被简化的针对特殊用途的委托

事件不是成员,不能使用对象创建表达式(new)来创建他们
由于事件不是成员: 必须声明在类或结构中,和其他成员一样   不能在一段可执行代码中声明事件

事件成员被隐式自动转化为null
        private  event MyDel myE;  //事件接受类型的返回值与委托匹配的事件处理程序
        public event MyDel MyE
        {
            add { myE += value; }
            remove { myE -= value; }
        }

例:


public delegate void MyDel(object sender,EventArgs e);
    public class Test
    {
        public event MyDel MyE;
        //public event PrintEventHandler MyE1, MyE2, MyE3;  //声明3个事件
        //public static event PrintEventHandler MyE4;       //声明静态事件
        public void Print()
        {
            if (MyE != null) 
            {
                MyE(this, new EventArgs());
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Test T = new Test();
            T.MyE += new MyDel(print1);
            T.MyE += new MyDel(print2);
            //T.Print();
            T.MyE -= new MyDel(print1);
            T.Print();
            Console.ReadKey();
        }
        static void print1(object sender, EventArgs e)
        {
            Console.WriteLine("1");
        }
        static void print2(object sender, EventArgs e)
        {
            Console.WriteLine("2");
        }
    }


接口


接口的特性:

1.接口类似于抽象基类,不能直接实例化接口;接口中的方法都是抽象方法,实现接口的任何非抽象类型都必须实现接口的所有成员:

2.接口不能包含常量、字段、运算符、实例构造函数、析构函数或类型、不能包含静态成员。

3.接口成员是自动公开的,且不能包含任何访问修饰符。

4.接口自身可从多个接口继承,类和结构可继承多个接口,但接口不能继承类。

5.接口声明不包含数据成员,只能包含方法、属性、事件、索引的静态成员函数的声明,函数成员的声明不包含任何实现代码而在每一个成员声明的主体后必须作用分号

6.接口的名称必须从大写的I开始

7.接口声明可以有访问修饰符,但接口成员不能有任何访问修饰符

8.如果类实现了接口,那么它必须实现接口的所有成员

9.如果类从基类继承并实现了接口,基类列表中的基类名称必须放在任何接口之前

10.只有类或结构才能实现接口

接口和抽象类的区别
接口用于规范,抽象类用于共性。
接口中只能声明方法,属性,事件,索引器。而抽象类中可以有方法的实现,也可以定义非静态的类变量。
抽象类是类,所以只能被单继承,但是接口却可以一次实现多个。
抽象类可以提供某些方法的部分实现,接口不可以。
抽象类的实例是它的子类给出的。接口的实例是实现接口的类给出的。
在抽象类中加入一个方法,那么它的子类就同时有了这个方法。而在接口中加入新的方法,那么实现它的类就要重新编写(这就是为什么说接口是一个类的规范了)。
接口成员被定义为公共的,但抽象类的成员也可以是私有的、受保护的、内部的或受保护的内部成员(其中受保护的内部成员只能在应用程序的代码或派生类中访问)。
此外接口不能包含字段、构造函数、析构函数、静态成员或常量

接口和类的区别
异:
不能直接实例化接口。
接口不包含方法的实现。
接口、类和结构可从多个接口继承。但是C# 只支持单继承:类只能从一个基类继承实现。
类定义可在不同的源文件之间进行拆分。
同:
接口、类和结构可从多个接口继承。
接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。
接口可以包含事件、索引器、方法和属性。
一个类可以实现多个接口。"


例:

    interface Iprogram
    {
        void Fun();
    }
    interface IAprogram
    {
        void Fun();
    }
    class Program : Iprogram, IAprogram
    {
        void Iprogram.Fun()  //显式实现接口成员
        {
            Console.WriteLine("I'm Fun.");
        }
        void IAprogram.Fun()
        {
            Console.WriteLine("I'm Fun");
        }
        public void Fun()   //隐式实现接口
        {
            Console.WriteLine("I am program fun.");
        }
        static void Main(string[] args)
        {
            //当显式实现该接口的成员时,实现的成员不能通过类实例访问,只能通过接口实例访问。
            Iprogram pro = new Program();  //声明一个接口实例,但不是对接口进行实例化
            pro.Fun();
            Program pr = new Program();
            ((Iprogram)pr).Fun();
            ((IAprogram)pr).Fun();

            //当隐式实现该接口的成员时,实现的成员可以通过类实例访问,也可以通过接口实例访问,但是实现的成员必须是公有的。
            Iprogram IP = new Program();
            IP.Fun();
            IAprogram IA = new Program();
            IA.Fun();
            Program P = new Program();
            P.Fun();
            Console.ReadKey();
        }
    }


集合


在ArrayList中主要使用Add、Remove、RemoveAt、Insert四个方法对栈进行操作

在Stack中主要使用Push,Pop,Peek三个方法对栈进行操作

在Queue中主要使用Enqueue、Dequeue、Peek三个方法对队进行操作

在Hashtable中主要使用Add、Remove两个方法对哈希表进行操作

在SortedList中主要使用Add、Remove、RemoveAt三个方法对SortedList进行操作



ArrayList 


ArrayList 动态数组    ArrayList a = new ArrayList();

Array 静态数组          Array[] a = new Array[10]; 

ArrayList数组的数据元素可以是任何类型,而且各个元素的类型可以不同


常用属性和方法:

Count:获得元素个数              ArrayList(Count属性 a.Count)

Capacity:设置ArrayList可包含元素个数


ArrayList a = new ArrayList(5);  //相当与ArrayList a = new ArrayList();    a.Capacity = 5;

Add:为对象赋值


            ArrayList a = new ArrayList(5); 
            a.Add("1");  //添加元素到数组的末尾
            a.Add("2");
            a.Add("3");


Insert:将元素插入 ArrayList 的指定索引处


           ArrayList a = new ArrayList(5);
           a.Insert(2, "5");
           Console.WriteLine(a);


InsertRange:将集合中的某个元素插入 ArrayList 的指定索引处


           ArrayList b = new ArrayList();
           a.InsertRange(1, b);


AddRange:将集合的元素添加到数组的末尾


            ArrayList b = new ArrayList();
            a.AddRange(b); 
            foreach (object j in a)
            {
                Console.Write(" "+j);
            }

Remove:从 ArrayList 中移除特定对象的第一个匹配项

RemoveAt:移除 ArrayList 的指定索引处的元素 RemoveRange 从 ArrayList 中移除一定范围的元素

Reverse:将整个 ArrayList 中元素的顺序反转

Clear:清除所有元素

FixedSize:检测ArrayList是否具有固定大小(返回bool类型的值)

            ArrayList a1 = ArrayList.FixedSize(a);
            Console.WriteLine(a1.IsFixedSize);


ReadOnly:检测a是否为只读(返回bool类型的值)


            ArrayList a2 = ArrayList.ReadOnly(a);
            Console.WriteLine(a2.IsReadOnly);


BinarySearch:搜索数组中的元素,返回从0开始的索引


ArrayList a= new ArrayList();
int p = a.BinarySearch("3");
if (p < 0)
{
    Console.WriteLine("未搜索到要找的元素");
}
else
{
    Console.WriteLine("要搜索的元素在第{0}位", p + 1);
}



Contains:搜索数组中元素是否存在


ArrayList a = new ArrayList(); //确定某元素是否在 ArrayList 中
if (a.Contains("5"))
{
    Console.WriteLine("Yes");
}
else
{
    Console.WriteLine("No");
}


Sort:对整个 ArrayList 中的元素进行排序

Equals:比较两个ArrayList中元素是否相等


object obj1 = new object();
object obj2 = new object();
Console.WriteLine(obj1.Equals(obj2));
obj1 = obj2; Console.WriteLine(obj1.Equals(obj2));


IndexOf:搜索指定的元素第一次出现的位置

TrimToSize:将容量设置为 ArrayList 中元素的实际数目

HashTable 

hashtable和SortedList都是表示键/值对的集合

hashtable是没有排序的,所以新增元素会比较快

而SortedList 存储的键值对是按key进行排序了的,因为要排序,所以新增元素时,要先查找元素的位置再插入,相对慢些,但是在查找时比较快

SortedList sl = new SortedList();

SortedList sl = new SortedList([最初可包含的元素数目]);

/ /添加 键/值对的集合


 sl.Add("1", "Hello");
sl.Add("2", "World");
sl.Add("3", "!");


//定义可设置的键/值对      

foreach (DictionaryEntry DE in ht)
{
      string s = DE.Key.ToString();
      string t = DE.Value.ToString();
      Console.WriteLine("键{0},值{1}",s,t);
}


Clear:从 Hashtable 中移除所有元素

Remove:从 Hashtable 中移除带有指定键的元素

Contains:判断哈希表是否包含特定键                  ContainsValue:判断哈希表是否包含特定值


if (ht.Contains("1"))
{
    Console.WriteLine(ht["1"]);
}
if (ht.ContainsValue("A"))
{
    Console.WriteLine("AAAAAA");
} 


CopyTo:将 Hashtable 元素复制到一维数组实例中的指定索引位置


ArrayList akeys = new ArrayList(ht.Keys);
akeys.Sort();
foreach (string s in akeys)
{
    Console.WriteLine("************" + ht[s]);
}


SortedList 

 

SortedList s2 = new SortedList();
s2.Add(4, "A"); s2.Add(3, "G"); s2.Add(8, "Y"); s2.Add(5, "AS"); s2.Add(1, "M"); //获取 SortedList 对象的指定索引处的键
Console.WriteLine(s2.GetKey(3));


//获取 SortedList 对象的指定索引处的值
Console.WriteLine(s2.GetByIndex(3));

//返回指定的值在 SortedList 对象中第一个匹配项的从零开始的索引
Console.WriteLine(" " + s2.IndexOfValue("Y"));

//返回 SortedList 对象中指定键的从零开始的索引
Console.WriteLine(" " + s2.IndexOfKey(3));


Queue   表示对象的先进先出集合

常用方法:

Enqueue:将对象添加到 Queue 的结尾处


Queue myQ = new Queue();
myQ.Enqueue("The"); myQ.Enqueue("quick"); myQ.Enqueue("brown"); myQ.Enqueue("fox");
foreach (string s in myQ)
{
    Console.Write(s+" ");
}
Console.WriteLine();


Dequeue:移除并返回位于 Queue 开始处的对象

Peek:用于返回位于 Queue 开始处的对象但不将其移除



Stack  表示对象的简单后进先出 (LIFO) 非泛型集合

常用方法:

Push:将对象插入Stack的顶部


Stack St = new Stack();
St.Push("a"); St.Push("c"); St.Push("b");
foreach (string s in St)
{
    Console.WriteLine(s);
}


Pop:移除并返回位于 Stack 顶部的对象

Peek:用于返回位于 Stack 顶部的对象但不将其移除



---------------------- Windows Phone 7手机开发.Net培训、期待与您交流! ----------------------

                                                                                                             详细请查看:http://edu.csdn.net/heima/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值