您的位置:首页 > 理论基础 > 计算机网络

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

2009-11-28 17:37 316 查看
一。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 语句
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐