今天跟大家分享一下关于访问限定和数据成员的知识。主要包括以下两点:

  • Abstract, sealed, virtual, new, override怎么用?
  • Const 和 readonly好像都表示不能改变的值,有什么区别呢?

一、 访问限定

类和方法有一些访问限定符,如private,public等。除此之外,还包含一些预定义特性。下面几个你都知道吗?

1. 类的预定义特性
  • Abstract——抽象类。不能实例化。如果派生类不是抽象类,则必须实例化。
  • Sealed——密封类。不能做基类被继承。

要想既不能实例化又不能被继承? 需要两个步骤:

  1. seadled修饰。防止被被继承 ;
  2. 私有化无参构造器。防止实例化自动调用默认无参构造函数。例如:

sealed class Demo

{

private Demo() { }

...

}

2. 方法的预定义特性
  • Abstract——用于抽象类中的抽象方法,该方法不能包含具体实现。派生类如果不实现该方法,则必须为抽象类。

public abstract class Animal

{

public abstract void Shout();

}

实例:

public class Animal //基类
    {

public virtual void Shout()     //定义虚方法
        {

Console.WriteLine("逼我发威啊!"); //虚方法实现

}

}

public class Dog : Animal  
    {

public override void Shout()    //override重写基类方法
        {

Console.WriteLine("汪汪!");

}

}

public class Cat : Animal
    {

public new void Shout()        //new隐藏基类方法
        {

Console.WriteLine("喵喵~~");

}

}

class Program
    {

static void Main(string[] args)
        {

new Animal().Shout();   //“逼我发威啊!”

new Dog().Shout();        //“汪汪!”

new Cat().Shout();        //”喵喵~~”

Console.WriteLine("**************************");

Animal a1 = new Dog();

a1.Shout();                  //重写了基类的方法   “汪汪!”

Animal a2 = new Cat();

((Cat)a2).Shout();       //派生类中的方法隐藏了基类的方法 ”喵喵~~”(类型是子类Cat)

a2.Shout();                 //基类的方法没有被修改,只是被隐藏 “逼我发威啊!”(类型是父类Animal)

Console.Read();

}

}

二、 数据成员——常量和只读

我们经常提到常量和只读,听上去都是不能改变的意思,那么它们到底有什么区别呢?
1. 常量const

常量是恒定不变的,在编译时就确定了它的值,编译后直接将值存到元数据中。变量类型只能是编译器能直接识别的基元类型,不能是引用类型,因为引用类型需要在运行时调用构造函数进行初始化。

我们给段代码实际看一下:

class TestConst    
   {
       public const int Number = 100;     //声明常量并赋值
       public string GetName()
       {
           const string name = "XiaoJing";    //常量用作局部变量
           return name;
       }
   }

class Program
   {

static void Main(string[] args)
       {
           Console.WriteLine("const:The total number is " + TestConst.Number);
           Console.Read();
       }
   }

通过ILDasm工具查看一下,const变量编译后为static literal类型,所以不难理解,常量是针对类的一部分,而不是实例的一部分。这样它才能保证是恒定不变的。

在使用常量时,编译器从常量模块的元数据中直接取出常量的值,嵌入到IL代码中。所以在声明常量的时候就要为它初始化值。例如上面的例子,Number直接替换为值100。

Main函数的IL代码如下:

还有一点,const常量也可以用于局部变量,例如上面的GetName()方法。

2. 只读字段readonly

类的数据成员通常用来保存一个值类型的实例或者指向引用类型的引用,CLR支持读写和只读两种数据成员,其中只读数据成员使用readonly修饰的。看个实际例子:

class TestReadonly
  {
      public readonly int Number = 100;   //只读实例成员
      public TestReadonly()
      {
          Number = 200;         //构造器中重新赋值
      }
  }

class Program
  {
      static void Main(string[] args)
      {
          Console.WriteLine("readonly:The total number is " + new TestReadonly().Number);
          Console.Read();
      }
  }

通过ILDasm.exe工具查看, Readonly实例成员编译后为 initonly修饰。这个例子是只读实例成员,readonly也可以修饰静态只读成员,需要在类静态构造器中初始化,这里就不赘述了。

数据成员是在类的实例构造过程中分配内存的,因此能在运行时刻获取它的值。因此只读成员类型没有限制,可以是基元类型,也可以是引用类型。而且可以在构造器中赋值,声明时赋值与否都可以。

我们查看main函数的IL代码:可以看出首先对TestReadonly类进行实例化,然后读取实例的Number成员的值,是在运行过程中获取值的。

还有要注意的一点,readonly不能用作局部变量,否则编译时就会报错。

最后我们要说明的是,readonly字段不能改变的是引用,而不是字段引用的对象。例如

public sealed class AType
    {
        public static readonly char[] chars = new char[] { 'a', 'b', 'c' };
    }
    public sealed class BType
    {
        public static void Change()
        {
            AType.chars[0] = 'X';
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(AType.chars[0]);
            BType.Change();
            Console.WriteLine(AType.chars[0]);
            Console.Read();
        }
    }

运行结果是

a

X

作者:丫头小静(Cathy) 
出处:http://www.cnblogs.com/janes/

转载于:https://www.cnblogs.com/changrulin/p/4778378.html

CLR via C#(05)- 访问限定、数据成员相关推荐

  1. 荐读|属性与可直接访问的数据成员之间应该如何选

    写在前面 在书写C#代码的时候你是否有过这样的经历:经常混用属性以及公有的数据成员.毕竟他们的用法基本一致,对于使用来说好像没什么区别啊.其实我也经常使用类的公有的数据成员来定义一些常量,为了简单,在 ...

  2. 1.1 - C#语言习惯 - 使用属性而不是可访问的数据成员

    属性一直是C#语言中的一等公民.自1.0版本以来,C#对属性进行了一系列的增强,让其表达能力不管提高.你甚至可以为setter和getter指定不同的访问权限. 隐式属性也极大降低了声明属性时的工作量 ...

  3. C++:静态成员函数访问静态数据成员(商店实际应用题)

    题目概述: 编程: #include< iostream> using namespace std; class Product { public: Product(int n, int ...

  4. 友元函数、友元类、访问私有数据成员、友元关系[C++]

    友元函数(friend function) 1. 什么是友元函数?     一个类的私有数据成员通常只能由类的函数成员来访问,而友元函数可以访问类的私有数据成员,也能访问其保护成员 2. 友元函数的用 ...

  5. 3第一周课后练习#183;阅读计划(3)-使用函数来访问私有数据成员

    /** Copyright (c) 2015, 计算机科学学院,烟台大学* All rights reserved.* 文件名:test.cpp* 作 靠:刘畅* 完成日期:2015年 3 一个月 2 ...

  6. 在C ++中访问类的数据成员

    Accessing a data member depends solely on the access control of that data member. If its public, the ...

  7. C++不同的数据成员类型

    C++不同的数据成员类型 C++为数据成员提供了多种选择,除了在类中简单地声明数据成员外,还可以创建static数据成员(类的所有对象共享).const数据成员.引用数据成员.const引用数据成员和 ...

  8. 什么是静态成员(静态数据成员和静态函数成员)

    目录 一:静态成员: 二:静态数据成员: 三:静态数据成员的特点: 四:访问静态数据成员 五:静态函数成员,如何定义成员函数 六:静态数据成员的特点. 一:静态成员: 在c++类中声明成员时, 加上s ...

  9. 对C++ static作用——修饰 数据成员(改变为静态数据成员)、 成员函数(改变为静态成员函数)

    **************************C++中的static的用法******************************** *************************** ...

  10. C++学习(五) 静态数据成员和静态成员函数

    文章目录 1.静态成员: 1.1.说明 1.2.格式 2.静态成员函数 2.1.说明 2.2.格式 1.静态成员: 1.1.说明 静态成员包括静态数据和静态成员函数. (1).静态数据成员的定义与普通 ...

最新文章

  1. swift轮播图代码
  2. 最大公约数+最小公倍数
  3. 小米手机qq不读取相册照片_小米手机越用越卡怎么办?
  4. SpringBoot 序列化与反序列化日期类型参数
  5. 什么是php工作流,什么是工作流?
  6. Python爬虫 senlenium爬取拉勾网招聘数据,你学会了吗
  7. jQuery开发之windows边栏小工具开发(Gadget development)- wi...
  8. php 车牌号 正则,php正则验证车牌格式的函数
  9. cat6 万兆_CAT6、CAT6A超六类和CAT7七类网线哪个更适合10GBASE-T万兆网络
  10. 动态推荐系统关键技术研究(一)
  11. 网页一直提示flash版本过低升级后还是不行
  12. 记忆训练 0-100的110个数字对应编码
  13. 二阶系统的单位阶跃响应_数学推导
  14. android开机卡logo,logcat怎么抓log
  15. 连接策略与搜索引擎优化
  16. 爬取起点中文网站原创风云榜小说排行
  17. numpy.core.multiarray failed to impor
  18. 单日涨粉10w+,他做了什么让流量和口碑都火爆?
  19. grep中使用\d匹配数字不成功的原因
  20. python安装绘图库_python绘图库Matplotlib的安装

热门文章

  1. 支付网站服务器费用怎么记账,支付云服务器的费用怎么做账
  2. xlwt设置单元格背景颜色
  3. win7装win10虚拟机出现问题
  4. 闭包函数到底是什么?有什么用?
  5. 趁着下班前五分钟书写——Vue3通讯(常规写法、语法糖、v-modle、兄弟通讯)
  6. opencv-python 二值图像的模板匹配实现
  7. 如何用EOF来实现连续输入输出,及如何停止
  8. 【开发工具】Adobe 全家桶 我再也不用乱找了 全都在这里
  9. 和数集团“区块链+数字化”促进新场景应用落地 为多领域开启无限可能
  10. tenable公司B轮融资