面向对象的基础是类和对象,而类是面向对象程序设计思想的灵魂。而类是对具有相同特征的一类事物的抽象。

就比如人是一个类,它是对人的抽象。而一个具体的人就是人这个类的一个对象。

类的定义

在定义类的时候需要使用class关键字,如下:

[访问修饰符] class 类名

{

   //类的主体

}

1.其中访问修饰符可以是public,protected,internal,private,protected,internal等

2.class是声明类的关键字,类名是自己定义的

3.大括号中声明的是类的成员

其中一般省略访问修饰符。对类的访问控制权需要用访问修饰符来定义,在C#中访问修饰符有以下5种

1.public:对类的访问不受限制。

2.protected:对类的访问仅限于包含类或从包含类派生的类。

3.private:访问仅限于包含类

4.internal:访问仅限于当前项目

5.protected internal :同时拥有protected的访问权限和internal的访问权限。

例如:

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

namespace ConsoleApplication2
{
    class Phone1
    {
        public string brand;//定义公有的成员表示电话的品牌
        public string phoneNumber;//定义公有的成员表示电话的电话号码
    }
    class Program
    {
        static void Main(string[] args)
        {
            Phone1 obj = new Phone1();//创建obj对象
            obj.brand = "侨兴";//为对象的成员brand赋值
            obj.phoneNumber = "037108080808";//为对象的成员phoneNumber赋值
            Console.WriteLine("电话的品牌是:"+obj.brand);//输出对象成员的brand的值
            Console.WriteLine("电话的号码是:"+obj.phoneNumber);//输出phoneNumber的值
            Console.Read();//暂停程序的运行,按任意键继续
        }

    
    }
    
}

运行结果:

类的成员

组成类的元素成为类的成员,类的成员主要包括描述状态的数据成员和描述操作的函数成员(方法),函数成员提供了操作类中数据的某些功能,包括属性,方法,索引器,事件,运算符,构造函数,析构函数等。

数据成员:包括字段,常量和事件

成员变量的定义语法为:

[访问修饰符] 数据类型 成员变量名

属性成员

属性是字段的一种自然扩展,是一个与类或对象相关的命名。与字段不同的是:属性不表示存储位置,属性拥有访问器,访问器定义了读取或者写入属性值时必须执行的代码,通过属性的get{}访问器和set访问器来实现对类中私有字段的读写操作。

为了实现类的封装性,一般把描述类的特征的字段定义为privact,把属性设为public来操作私有的字段

属性的定义格式如下:

[访问修饰符] 数据类型 属性名

{

   get

     {}

    set

       {}

}

其中属性的访问修饰符是用来指定方法的访问级别的,主要的访问修饰符和数据成员的访问修饰符一样。属性方法的命名通常使用帕斯卡命名法,即首字母大写。

方法成员

方法是描述对象行为的,对类的数据成员的操作都封装在类的方法中,方法的主要功能就是操作数据,没有方法的程序是没有意义的。

(自己的理解:其实方法就是程序,就是一些有序的操控数据的语句,就是表达式)

方法的声明格式如下:

[访问修饰符] 返回值类型 方法名(参数列表)

{

     方法体

}

1,方法的访问修饰符是用来指定方法的访问级别,主要的访问修饰符和属性的访问修饰符一样。

2,方法的返回值类型可以是任意一种C#的数据类型,如果没有返回值,就用关键字void表示。

3,方法名的命名和属性一样,建议用名称和动词的组合表示。(方法名与类名相同时为构造方法或者构造函数)

4,方法可以有参数,也可以没有参数,多个参数之间用“,”分隔,没有参数也不能省略“()”。

5,方法体通常是方法完成功能所要执行的代码。

静态成员

静态成员是和类相关联的,不依赖于特定的对象,可以作为类中“共”有的成员。如果类的某个成员声明时使用了static关键字,该成员就变成了静态成员。在类中可以定义为静态成员的有:字段,方法,属性,运算符,事件,和构造函数等。但不能是:索引器,析构函数。

静态成员可以直接使用,不必创建对象,可以通过“类名.静态成员”的方式使用静态成员。

简单些理解就是静态成员为类的所有对象共享,非静态成员也叫实例成员,实例成员属于具体的对象。

例如:

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

namespace ConsoleApplication2
{
    public class Phone
    {
        public const string PhoneType = "GSM";//声明常量,隐士为静态
        public static string emergency_Call = "119";//声明静态字段
        private string phoneNumber;//声明私有变量,表示电话号码
        public string PhoneNumber//声明属性,设置和获取phoneNumber的值
        {
            get
            {
                return phoneNumber;//得到phoneNumber的值
            }
            set
            {
                phoneNumber = value;//设置phoneNumber的值
            }
        }
        public void Dial()//无参数的方法成员,表示电话具有拨打功能。
        {
            Console.WriteLine("您正在打电话!");
        }
        public void Dial(string number)//有参数的方法成员,表示电话这时候拨打一个具体的电话号码
        {
            Console.WriteLine("您正在拨打:"+number);
 
        }
        public static void EmergencyCall()//定义静态方法成员EmergencyCall
        {
            Console.WriteLine("您正在拨打急救电话119!");
 
        }

    }

        class Program
        {
            static void Main(string[] args)
            {
                Phone.EmergencyCall();//静态方法,通过类名直接调用。
                Console.WriteLine(Phone.emergency_Call);//静态字段通过类名直接调用。
                Phone objPhone = new Phone();
                objPhone.PhoneNumber = "13888888888";//通过set访问器给私有变量phoneNumber赋值
                Console.WriteLine("电话号码是:"+objPhone.PhoneNumber);//通过get访问器得到私有变量phoneNumber的值
                objPhone.Dial();//无参的实例方法。
                objPhone.Dial("13877978990");//有参的实例方法。
                Console.ReadKey();

            }


        }


    }

 

运行结果:

 

对象

类和对象是密不可分的,有类就有对象,有对象就有类。

客观世界是由多种对象组成的,用面向对象的思想来编写程序,就是要把一切都看成对象。

概念:

类是具有相同特征的一类事物的抽象,而对象是类的实例。类和对象有着本质的区别:类是从对象中抽取出来的一类对象的描述,对象是类中的个体,是一个具体的事物,创建对象就是从抽象到具体的过程,是将类的属性和行为的实例化的过程。

 

对象的创建和使用

类是抽象的,要使用类中非静态的成员,就必须创建类的对象,创建对象就是类的实例化的过程。C#使用new运算符来创建对象。格式如下:

类名 对象名=new 类名(参数列表)

其中参数列表是可选的。

对象的使用是通过访问对象中的非静态成员来实现的,访问对象中的非静态成员的语法如下:

对象名.成员名。

匿名类型和对象初始化器

匿名类型和对象初始化器是C#3.0新增的功能,能简化对象的初始值设置。使用对象初始化,创建Phone类的对象并对其属性成员PhoneNumber赋值可以这样写:

Phone objPhone=new Phone(){PhoneNumber=“12345689”};

例如定义类Point,有两个属性X和Y表示点的坐标

Public Class Point

{                                                //类的属性定义中的get和set访问器可以简写如下形式

      Public int X{get;set;}             //定义属性X,得到和设置点的横坐标

      Public int Y{get;set;}               //定义属性Y,得到和设置点的纵坐标

}

 使用对象初始化,就可以这样创建对象并对属性赋值:

Point p=new Point(){X=0;Y=0};

使用匿名类型可以定义内嵌的类型,不需要显示地定义一个类型。假设没有定义Point类,却要使用一个Point的对象(即使匿名的),可以使用对象初始化器,不用指定类名。如:

var p=new {X=0;Y=0};

构造函数和析构函数

构造函数是类的特殊方法成员,名称与类名相同,主要完成对象的初始化。

C#通过new创建对象的过程实际上就是调用类的构造函数的过程,创建对象时调用构造函数对对象进行初始化,每个类都有构造函数,如果没有定义,系统会提供一个默认的构造函数

默认的构造函数一般不进行什么操作。在访问一个类的时候,系统最先执行构造函数中的语句。

析构函数是对象销毁前释放所占用系统资源的类成员,析构函数的名字是在类名前面加一个“~”符号组成。析构函数不接受任何参数,也不返回任何值

例如:

Public class MyClass//声明类MyClass

{

    ~MyClas()//析构函数名

           {

                   //析构函数

              }

}

一个类只能有一个析构函数,析构函数不能手动调用,是系统自动调用的。

例:

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

namespace ConsoleApplication2
{
    public class Point
    {
        public int X { get; set; }
        public int Y { get; set; }
        public Point()
        {
            X = 0;
            Y = 2;
        }
        public Point(int val_x, int val_y)
        {
            X = val_x;
            Y = val_y;
        }
        ~Point()
        {
            Console.WriteLine("析构函数主要用于清理资源!");
            Console.ReadKey();
        }

    }

        class Program
        {
            static void Main(string[] args)
            {
                Point objPoint1 = new Point();
                Console.WriteLine("无参构造函数的演示!");
                Console.WriteLine("X="+objPoint1.X);
                Console.WriteLine("Y="+objPoint1.Y);
                Point objPoint2 = new Point(80,90);
                Console.WriteLine("有参数构造函数的演示:");
                Console.WriteLine("X="+objPoint2.X);
                Console.WriteLine("Y="+objPoint2.Y);

             
                Console.ReadKey();

            }


        }


    }

运行结果

 

参数的传递

C#的许多方法成员的是有参数的,定义方法时声明的参数是形式参数(或叫虚拟参数),调用方法时要给形式参数传值,传递的值是实在的参数。

C#中有“值传递“和”引用传递”两种传递参数的类型(默认为值传递)。

使用值传递方式时,向形式参数传递的是实在参数的副本,方法内发生的对形式参数的更改对实在参数本身没有任何影响,就像文件的复印件一样,无论如何修改复印件,原件没有任何改变。

如果希望所调用的方法能更改实在参数的值则必须使用ref或out关键字声明通过引用传递方式传递参数。引用传递是把实在参数的地址传递给形式参数,形式参数和实在参数指向同一个存储单元,对形式参数的改变就是对实在参数的改变。out传递与ref类似。二者的区别是:ref要求参数在传递之前必须初始化,out则不需要初始化。

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

namespace ConsoleApplication2
{
   

        class Program
        {
            static void Main(string[] args)
            {
                int num1 = 3;//定义变量num1
                int num2 = 8;//定义变量num2
                Console.WriteLine("此实例演示值传递参数");
                Console.WriteLine("交换之前的字符串顺序为{0},{1}",num1,num2);
                Swap(num1,num2);//调用交换方法
                Console.WriteLine("交换之后的字符串顺序为{0},{1}",num1,num2);//输出调用交换方法之后的结果。
                Console.ReadKey();

            }

            private static void Swap(int num1, int num2)
            {
                int temp;//定义交换变量的中间变量
                temp = num1;//将num1的值赋给中间变量temp
                num1 = num2;//将num2的值赋给num1
                num2 = temp;//将中间变量temp中存储的num1的原来值给num2
            }


        }


    }

运行结果

 

由运行结果可以看出两个变量的值并没有进行交换,这就是值传递。

下面采用引用传递参数。

 private static void Swap(int num1, int num2)

修改为:

  private static void Swap(ref int num1, ref int num2)

例如:

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

namespace ConsoleApplication2
{
   

        class Program
        {
            static void Main(string[] args)
            {
                int num1 = 3;//定义变量num1
                int num2 = 8;//定义变量num2
                Console.WriteLine("此实例演示引用传递参数");
                Console.WriteLine("交换之前的字符串顺序为{0},{1}",num1,num2);
                Swap(ref num1,ref num2);//调用交换方法
                Console.WriteLine("交换之后的字符串顺序为{0},{1}",num1,num2);//输出调用交换方法之后的结果。
                Console.ReadKey();

            }

            private static void Swap(ref int num1, ref int num2)
            {
                int temp;//定义交换变量的中间变量
                temp = num1;//将num1的值赋给中间变量temp
                num1 = num2;//将num2的值赋给num1
                num2 = temp;//将中间变量temp中存储的num1的原来值给num2
            }


        }


    }

运行结果:

由运行结果可以看出两个变量的值确实发生了改变。这也就是引用传递。

out关键字和ref关键字类似,也是声明引用传递参数的,但ref要求变量必须在传递之前对实在参数初始化。而out参数传递的变量不需要在传递之前初始化,但需要调用方法在方法返回之前对out传递的参数赋值。当希望方法返回多个值时,可以使用out方式,使用out参数的方法可以将变量用作返回类型,还可以将一个或多个对象作为out参数返回给调用方法。

例如:

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

namespace ConsoleApplication2
{
   
       
   

        class Program
        {
            static void Main(string[] args)
            {
                int value;//定义int变量value
                string str1, str2;//定义两个字符串变量
                Console.WriteLine("此实例演示out引用传递");
                Method(out value,out str1,out str2);//调用Method方法得到3个返回值赋给3个实参。
                Console.WriteLine("参数value的值是"+value);//此时value的值是44
                Console.WriteLine("参数str1的值是"+str1);//此时参数str1的值是:I've been returned
                Console.WriteLine("参数str2的值是" + str2);//此时str2的值是空(null)
                Console.ReadKey();

            }

        static void Method(out int i, out string s1, out string s2)//定义静态方法使用out进行参数的传递
        {
            i = 44;//参数i赋值为44
            s1 = "I've been returned";//参数s1赋值为“I've been returned”
            s2 = null;//参数s2赋值为null
        }


        }


    }

运行结果:

分部类

一般来说,一个类,结构或结构位于一个源文件中,但某些情况,比如大型项目,特殊部署时,可能需要把一个类,结构或结构放在几个文件中来处理。等到编译时,自动地把他们组合起来成为一个完整的类。

分部类适用于以下几种情况。

1.类型特别大,不宜放在一个文件中实现。

2,一个类型中的一部分代码为自动化工具生成的代码。不宜与我们自己编写的代码混合在一起。

3,需要多人合作编写一个类。

分部类是一个纯语言层的编译处理,不影响任何执行机制,事实上C#编译器在编译的时候仍会将各个部分的局部类型合并成一个完整的类。

C#分部类是在class前面添加关键字partial来定义的。

例如在一个文件中声明分部类Person的代码

如下:

Public partial class Person

{

   Public void DoWork()

     {   

             //定义方法

         }

 

}

在另一个文件中声明分部类Person

public partial class Person

{

       public void GoToLunch()

          {

                  //定义方法

          }

}

 

Person类编译后拥有DoWork()和GoToLunch()两个方法。

分部类中还可以声明分部方法,分部方法是将方法的定义和实现分隔开,在方法前面用partial关键字修饰的方法就是分部方法。

如:

在一个文件中定义分部方法

public partial class Person

{  

        partial void DoWork();//定义分部方法

}

 

在另一个文件中实现分部方法

public partial class Person

{

   partial void DoWork()

       {

               //实现分部方法代码

       }

}

分部方法隐式为private类型,不可使用public访问修饰符。分部方法不可有返回值。

结构与类

结构和类相似,通常用来封装小型的相关变量组。

结构是一种值类型,通常创建结构要比创建类的速度快。

在C#中可以将结构看成轻量级的类。定义结构和类的定义是相似的,采用struct进行定义。

每一个struct类型数据可以是常量,变量,构造函数,方法和属性等成员。

定义结构的语法如下:

<访问修饰符>struct结构名

{

     //结构体

}

使用结构通过声明结构体变量或使用new来实例化结构对象,然后通过"结构体变量.结构成员名"或“结构对象.结构成员”的方式来使用结构。

例如定义表示学生信息的结构:

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

namespace ConsoleApplication2
{

    struct Student//定义结构Student
    {
        public string stuNum;//定义结构成员表示学生学号
        public string stuName;//定义结构成员表示学生姓名
        public int stuAge;//定义结构成员表示学生年龄
        public int stuClass;//定义结构成员表示学生班级
        public int stuGrade;//定义结构成员表示学生年级
        public Student(string stuNum, string stuName, int stuAge, int stuClass, int stuGrade)//结构的构造函数,用参数给结构中的成员赋值
        {
            this.stuNum = stuNum;//将参数stuNum赋给this.stuNum
            this.stuName = stuName;//将参数stuName赋给this.stuName
            this.stuAge = stuAge;//将参数stuAge赋给this.stuAge
            this.stuClass = stuClass;//将参数stuClass赋给this.stuClass
            this.stuGrade = stuGrade;//将参数stuGrade赋给this.stuGrade
        }
        public void DoHomeWork()//结构中的方法
        {
            Console.WriteLine("正在学习!写作业");
 
        }
    }
   

        class Program
        {
            static void Main(string[] args)
            {

                Student goodStu;
                goodStu.stuNum = "110";
                goodStu.stuName = "Anderson";
                goodStu.stuAge = 19;
                goodStu.stuClass = 1;
                goodStu.stuGrade = 1;
                Console.WriteLine("结构的演示");
                Console.WriteLine("三好学生:学号:{0},姓名:{1},年龄:{2},班级:{3}", goodStu.stuNum, goodStu.stuName, goodStu.stuAge, goodStu.stuClass);//输出结构中的成员
                goodStu.DoHomeWork();//调用结构的方法
                Student normalstu = new Student("119","Bliss",18,1,1);
                Console.WriteLine("普通学生:学号:{0},姓名:{1},年龄:{2},班级:{3}", normalstu.stuNum, normalstu.stuName, normalstu.stuAge, normalstu.stuClass);//输出结构中的成员
                normalstu.DoHomeWork();
                Console.ReadKey();

            }

      


        }


    }

运行结果

 

类和结构的关系

类和结构实际上都是创建对象的模板,都可以包含构造函数,常数,字段,方法,属性,索引器,和运算符等成员。二者的区别如下:

1,结构是值类型,类是引用类型,在内存中结构是存储在堆栈上的值类型,类是存储在堆上的引用类型。

2,结构的构造函数和类的构造函数不同:结构不能包含显式的无参构造函数,结构成员会自动初始化为它们的默认值。结构不能包含以下形式的初始值设定类:base(参数列表)

3,对于结构中的实例字段成员,不能在声明时赋值初始化。

4,声明了结构类型后,可以使用new运算符创建构造对象,也可以不使用new关键字。如果不使用new,那么在初始化所有字段之前,字段将保持未赋值状态且对象不可用。

5,结构不支持继承,即一个结构不能从另一个结构或类继承,而且不能作为一个类的基类。

命名空间

命名空间是.NET避免名称冲突的一种方式。

例如,定义类Customer表示一个顾客同时其他人也可以定义一个Customer类,只要二者不在同一命名空间中就不会引起冲突。

在一个命名空间中可以有多个类,结构,接口等,在同一命名空间中类名,接口等不能同名。

命名空间不过是数据类型的一种组合方式,但命名空间中所有数据类型的名称都会自动加上该命名空间的名字作为其前缀。

命名空间可以相互嵌套。如果没有显式提供命名空间,则默认为项目名作为命名空间。

Using关键字

把一个类型放在命名空间中,可以有效的给这个类型指定一个较长的名字,该名称包括类型的命名空间,后面是句点“.”和类型的名称。

例如:

System.Windows.Forms.MessageBox.Show("Hello C#"),使用起来很不方便。为此可以使用Using关键字引入其命名空间。

导入命名空间的语法为:

using 命名空间名称;

当using指令引用的两个命名空间包含同名的类,就必须使用完整的名称以确保编译器知道访问哪个类型。

 

posted @ 2016-05-17 19:38  小李少  阅读(326)  评论(0编辑  收藏  举报