constants & start readonly & share的区别(整理自网络&msdn)

一。const型表达式的值在编译时形成,而static   readonly表达式的值直到程序运行时才形成。

       有时你不想在在程序运行时改变域,如运行时程序依靠的数据文件,一个math类的pi值,或者任何在程序运行时你不想改变的值。为了处理这种情况,c#中定义了两个近似的、相关的成员类型:contants和read-only域。  
   
  Constants域  
   
  从字面可以看出,常数(用关键字const表示)在应用程序运行期间保持不变。当定义某个事物为const时记住两个规则:第一,定义成常数的成员的值是在编译时设置的——或者是由编程者指定,或者是由编译器设置缺省值;第二,一个常数成员的值必须被写为一个字面常数。  
  为了定义一个常数域,在要定义的成员前使用一个const关键字,如下所示:  
   
  using   System;  
   
  class   MagicNumbers  
  {  
  public   const   double   pi   =   3.1415;  
  public   const   int   answerToAllLifesQuestions   =   42;  
  }  
   
  class   ConstApp  
  {  
  public   static   void   Main()  
  {  
  Console.WriteLine("pi   =   {0},   everything   else   =   {1}",  
  MagicNumbers.pi,   MagicNumbers.answerToAllLifesQuestions);  
  }  
  }  
   
  请注意这个代码的一个关键点——不必在客户端实例化MagicNumbers类,因为const成员缺省是静态的。为了更清楚的展示它,我们列出这两个域在MSIL中生成时的情况:  
   
  answerToAllLifesQuestions   :   public   static   literal   int32   =   int32(0x0000002A)  
  pi   :   public   static   literal   float64   =   float64(3.1415000000000002)  
   
  Read-only   域  
   
  使用const域是非常有用的,因为他清楚的表明了编程者的意图。然而,这只能用于在编译时已经知道值的情况下。所以,当一个域只有在运行时才能知道值而且一旦初始化以后值便不能改变的情况下,编程者该怎么办呢?C#语言的设计者用Read-only域的办法解决了这个问题(在其他语言中一般不会处理)。  
  当你用readonly关键字定义了一个域时,你只能在一个地方设置这个域的值——构造函数。以后,域的值便不能被自身类或者使用这个类的客户改变。让我们看一个图形应用程序记录屏幕分辨率的例子。你不能用const处理这个问题,因为应用程序直到运行时才能确定终端用户的屏幕分辨率,所以你必须使用这样的代码:  
   
  using   System;  
   
  class   GraphicsPackage  
  {  
  public   readonly   int   ScreenWidth;  
  public   readonly   int   ScreenHeight;  
   
  public   GraphicsPackage()  
  {  
  this.ScreenWidth   =   1024;  
  this.ScreenHeight   =   768;  
  }  
  }  
   
  class   ReadOnlyApp  
  {  
  public   static   void   Main()  
  {  
  GraphicsPackage   graphics   =   new   GraphicsPackage();  
  Console.WriteLine("Width   =   {0},   Height   =   {1}",  
  graphics.ScreenWidth,    
  graphics.ScreenHeight);  
  }  
  }  
   
  猛一看,这个代码正是我们需要的。然而,还有一点小问题:我们定义的readonly域是一个实例域,这意味着是用户在使用域之前必须先实例化类。这可能也不是什么问题,甚至这正是你想做的——在实例化类的时候正可以初始化readonly域的值。但如果你想要一个被定义成静态的、能在运行时被初始化的常数时该怎么办呢?这时,我们可以定义一个带static和readonly修饰符的域。然后,创建一个构造函数的特殊类型——static   constructor。静态函数可以用来初始化static域、readonly域或其他的域。现在我们改变先前的例子,给屏幕分辨率域加上static和readonly,并且增加一个静态构造函数。  
   
  using   System;  
   
  class   GraphicsPackage  
  {  
  public   static   readonly   int   ScreenWidth;  
  public   static   readonly   int   ScreenHeight;  
   
  static   GraphicsPackage()  
  {  
  //   Code   would   be   here   to    
  //   calculate   resolution.  
  ScreenWidth   =   1024;  
  ScreenHeight   =   768;  
  }  
  }  
   
  class   ReadOnlyApp  
  {  
  public   static   void   Main()  
  {  
  Console.WriteLine("Width   =   {0},   Height   =   {1}",    
  GraphicsPackage.ScreenWidth,    
  GraphicsPackage.ScreenHeight);  
  }  
  }   
    
   
二。何时使用 Shared
共享类或结构的成员使每个实例都可以使用该成员,而不必让每个实例保留自己的副本。例如,如果一个变量的值应用于整个应用程序,这点很有用。如果声明该变量为 Shared,那么所有实例会访问相同的存储位置,而如果一个实例更改了变量值,所有实例都会访问更新后的值。

规则
声明上下文。只能在模块级使用 Shared。这意味着 Shared 元素的声明上下文必须为一个类、结构或模块,而不能是源文件、命名空间或过程。

组合修饰符。不能在同一声明中将 Shared 与 Overrides、Overridable、NotOverridable、MustOverride 或 Static (Visual Basic) 同时指定。

访问。通过用类或结构名称而不是类或结构的特定实例的变量名称限定一个共享元素来访问它。您甚至不必创建类或结构的实例就可以访问它的共享成员。

下面的示例调用由 Double 结构所公开的共享过程 IsNaN。

If Double.IsNaN(result) Then MsgBox("Result is mathematically undefined.")

隐式共享。您无法在 Const 语句 (Visual Basic) 中使用 Shared 修饰符,但常数会被隐式共享。同样,您无法将模块或接口的成员声明为 Shared,但它们会被隐式共享。

行为
存储。共享变量或事件只能在内存中存储一次,而无论您创建多少个它的类或结构的实例。同样,共享过程或属性仅存储一组局部变量。

通过实例变量进行访问。可以通过用包含类或结构的特定实例的变量名称限定一个共享元素来访问它。虽然这通常会按预期设想起作用,但编译器会生成一条警告消息,并使访问通过类或结构名称而不是变量来进行。

通过实例表达式进行访问。通过返回类或结构实例的表达式访问共享元素时,编译器会使访问通过类或结构名称而不是计算表达式来进行。如果您要表达式执行其他操作以及返回实例,将产生意外结果。下面的示例演示这一点。

  复制代码
Sub main()
    shareTotal.total = 10
    ' The preceding line is the preferred way to access total.
    Dim instanceVar As New shareTotal
    instanceVar.total += 100
    ' The preceding line generates a compiler warning message and
    ' accesses total through class shareTotal instead of through
    ' the variable instanceVar. This works as expected and adds
    ' 100 to total.
    returnClass().total += 1000
    ' The preceding line generates a compiler warning message and
    ' accesses total through class shareTotal instead of calling
    ' returnClass(). This adds 1000 to total but does not work as
    ' expected, because the MsgBox in returnClass() does not run.
    MsgBox("Value of total is " & CStr(shareTotal.total))
End Sub
Public Function returnClass() As shareTotal
    MsgBox("Function returnClass() called")
    Return New shareTotal
End Function
Public Class shareTotal
    Public Shared total As Integer
End Class
 

在前面的示例中,编译器在代码通过实例访问共享变量 total 时两次都生成警告消息。每次它都使访问直接通过类 shareTotal 来进行,而不利用任何实例。在特意调用过程 returnClass 的情况下,意味着它甚至不会生成对 returnClass 的调用,因此不会执行显示“Function returnClass() called”的额外操作。

Shared 修饰符可用于下面的上下文中:

Dim 语句

Event 语句

Function 语句

运算符语句

Property 语句

Sub 语句

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值