C#中对象和类型

开发工具与关键技术:对象和类型

作者:邓崇富

撰写时间:2019 年6 月 30 日

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

类和结构:

类和结构实际上都是创建对象的模板,每个对象都包含数据,并提供了处理和访问数据的方法。类定义了类的每个对象(称为实例)可以包含什么数据和功能。例如,如果一个类表示一个顾客,就可以定义字段CustomerID、Name和Address,以包含顾客的信息。还可以定义处理在这些字段中存储的数据的功能。接着,就可以实例化类的一个对象,来表示某个顾客,为这个实例设置相关字段的值,并使用其功能。

public class PhoneCustomer

    {

        public const string DayOfSendBill = "Monday";

        public int CustomerID;

        public string Name;

 }

解构不同于类,因为它们不需要在堆上分配空间(类是引用类型,总是存储在堆(heap)上),而结构是值类型,通常存储在栈(stack)上,另外,结构不支持继承。

较小的数据类型使用结构可提高性能。但在语法上,结构与类非常相似,主要的区别是使用关键字struct代替class来声明的结构。例如,如果希望所有的PhoneCustomer实例都分布在栈上,而不是分布在托管堆上,就可以编写成下面的语句:

public struct PhoneCustomerStruct

    {

        public const string DayOfSendBill = "Monday";

        public int CustomerID;

        public string Name;

 }

对于类和结构,都使用关键字new来声明实例:这个关键字创建对象并对其进行初始化。在下面的例子中,类和结构的字段值都默认为0:

//对象实例化

     var myCustomer = new PhoneCustomer();

     //结构实例化

 var myCustomer2 = new PhoneCustomerStruct();

在大多数情况下,类要比结构常用得多。因此先指出类和结构得区别,以及选择使用机构而不使用类得特殊原因,但除非特别说明,否则就可以假定用于类的代码也适用于结构。

类:

类包含成员,成员可以是静态或实例成员。静态成员属于类;实例成员属于对象。静态字段的值对每个对象都是相同的,而每个对象的实例字段都可以有不同的值。静态成员关联了static修饰符。下面详细说说类的成员:

字段:

字段是与类相关的变量。前面的例子已经使用了PhoneCustomer类中的字段。一旦实例化PhoneCustomer对象,就可以使用语法Object.FieldName来访问这些字段,如下例所示:

var myCustomer = new PhoneCustomer();

            myCustomer.CustomerID = 1234;

        myCustomer.Name = "小红";

常量与类的关联方式和变量与类的关联方式相同。使用const关键字来声明常量。如果把它声明为public,就可以在类中的外部访问它

public class PhoneCustomer

       {

           public const string DayOfSendBill = "Monday";

           public int CustomerID;

           public string Name;

    }

最好不把字段声明为public。如果修改类的公共成员,使用这个公共成员的每个调用程序也需要更改。例如。如果希望在下一个版本中检查最大的字符串长度,公共字段就需要更改为一个属性。使用公共字段的现有代码,必须重新编译,才能使用这个属性(尽管在1调用程序看来,语法与属性相同)。如果只在现有的属性中改变检查,那么调用程序不需要重新编译就能使用新版本。最好把字段声明为private,使用属性来访问字段。

属性:

属性(property)的概念是:它是一个方法或一对方法,在客户端代码看来,是一个字段。下面把前面示例中变量名为_firstName的名字字段改为私有。FirstName属性包含get和set访问器,来检索和设置支持字段的值:

public class PhoneCustomer

    {      

        private string _Name;

        public string Name

        {

            get { return _Name; }

            set { Name = value; }

        }

 }

Get访问器不带任何参数,且必须返回属性声明的类型。也不应为set访问器指定任何显式参数,但编译器假定它带一个参数,其类型也与属性相同,并表示为value。

下面的示例使用另一个命名约定。下面的代码包含一个属性Age,它设置了一个字段age。在这个例子中,age表示Age的后备变量。

private int age;

        public int Age

         {

            get { return age; }

            set { age = value; }

      }

自动实现的属性:

如果属性的set和get访问器中没有任何逻辑,就可以使用自动实现的属性。这种属性会自动实现后备成员变量。前面Age示例的代码如下:

public int Age { get; set; }

不需要声明私有字段。编译器会自动创建它。使用自动实现的属性,就不能直接访问字段,因为不知道编译器生成的名称。

使用自动实现的属性,就不能在属性设置中验证属性的有效性,所以在上面的例子中,不能检查是否设置了无效的年龄。

自动实现的属性可以使用属性初始化器来初始化:

public int Age { get; set; } = 43;

属性的访问修饰符:

C#允许给属性的get和set访问器设置不同的访问修饰符,所以属性可以有公有的get访问器和私有的或受保护的set访问器。这有助于控制属性的设置方式或时间。在下面的代码示例中,注意set访问器有一个私有访问修饰符,而get访问器没有任何访问修饰符。这表示get访问器具有属性的访问及别。在get和set访问器中,必须有一个具备属性的访问级别。如果get访问器的访问级别是protected,就会产生一个编译错误,因为这会使两个访问器的访问级别都不是属性。

public class Class2

    {

        private string _name;

        public string Name

        {

            get

            {

                return _name;

            }

             private set

            {

                _name = value;

            }

          }

    }

方法:

注意,正式的C#术语区分函数和方法。在C#术语中,“函数成员”不仅包含方法,也包含类或结构的一些非数据成员,如索引器、运算符、构造函数和析构函数等,甚至还有属性。这些都不是数据成员,字段、常量和事件才是数据成员。

方法的声明,在C#中,方法的定义包括任意方法修饰符(如方法的可访问性)、返回值的类型,然后依次是方法名、输入参数的列表(用圆括号括起来)和方法体(用花括号括起来)。

每个参数都包括参数的类型名和在方法体中的引用名称。但如果方法有返回值,则return语句就必须与返回值一起使用,以指定出口点,例如:

public bool IsSquare(Rectangle rect)

           {

              return (rect.Height == rect.width);

        }

如果没有返回值,就把返回类型指定为void,因为不能省略返回类型。如果方法不带参数,仍需要在方法名的后面包含一对空的圆括号()。此时return语句就是可选的,当到达右花括号时,方法会自动返回。

调用方法:

在下面的例子中,说明了类的定义和实例化、方法的定义和调用的语法。类Math定义了静态成员和实例化成员:

public class Math

        {

            public int Value { get; set;}

            public int GetSquare() => Value * Value;

            public static int GetSquareOf(int x) => x * x;

            public static double GetPi() => 3.14159;

    }

Program类利用Math类,调用静态方法,实例化一个对象,来调用实例成员:

using static System.Console;

namespace MathSample

    {

        class Program

        {

            static void Main()

            {

                //Try calling some static functions.

                WriteLine($"Pi is {Math.GetPi()}");

                int x = Math.GetSquareOf(5);

                WriteLine($"Square of 5 is {x}");

                var math = new Math();

                math.Value = 30;

                WriteLine($"Value field of math variable contains {math.Value}");

                WriteLine($"Square of 30 is {math.GetSquare()}");

            }

          }

   }

运行MathSample示例,结果如下

Pi is 3.14159

            Square of 5 is 25

            Value field of math variable contains 30

        Square of 30 is 900

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值