分享
 
 
 

17.4 Fields

王朝other·作者佚名  2006-05-09
窄屏简体版  字體: |||超大  

A field is a member that represents a variable associated with an object or

class. A field-declaration introduces

one or more fields of a given type.

field-declaration:

attributesopt field-modifiersopt type variable-declarators ;

field-modifiers:

field-modifier

field-modifiers field-modifier

Chapter 17 Classes

221

field-modifier:

new

public

protected

internal

private

static

readonly

volatile

variable-declarators:

variable-declarator

variable-declarators , variable-declarator

variable-declarator:

identifier

identifier = variable-initializer

variable-initializer:

expression

array-initializer

A field-declaration may include a set of attributes (§24), a new modifier (

§17.2.2), a valid combination of the

four access modifiers (§17.2.3), and a static modifier (§17.4.1). In

addition, a field-declaration may include a

readonly modifier (§17.4.2) or a volatile modifier (§17.4.3), but not

both The attributes and modifiers apply

to all of the members declared by the field-declaration. It is an error for

the same modifier to appear multiple

times in a field declaration.

The type of a field-declaration specifies the type of the members

introduced by the declaration. The type is

followed by a list of variable-declarators, each of which introduces a new

member. A variable-declarator

consists of an identifier that names that member, optionally followed by an

?=? token and a variable-initializer

(§17.4.5) that gives the initial value of that member.

The type of a field must be at least as accessible as the field itself (§10.

5.4).

The value of a field is obtained in an expression using a simple-name (§14.5

.2) or a member-access (§14.5.4).

The value of a non-readonly field is modified using an assignment (§14.13).

The value of a non-readonly field

can be both obtained and modified using postfix increment and decrement

operators (§14.5.9) and prefix

increment and decrement operators (§14.6.5).

A field declaration that declares multiple fields is equivalent to multiple

declarations of single fields with the

same attributes, modifiers, and type. [Example: For example

class A

{

public static int X = 1, Y, Z = 100;

}

is equivalent to

class A

{

public static int X = 1;

public static int Y;

public static int Z = 100;

}

end example]

17.4.1 Static and instance fields

When a field declaration includes a static modifier, the fields introduced

by the declaration are static fields.

When no static modifier is present, the fields introduced by the

declaration are instance fields. Static fields

C# LANGUAGE SPECIFICATION

222

and instance fields are two of the several kinds of variables (§12)

supported by C#, and at times they are referred

to as static variables and instance variables, respectively.

A static field is not part of a specific instance; instead, it identifies

exactly one storage location. No matter how

many instances of a class are created, there is only ever one copy of a

static field for the associated application

domain.

An instance field belongs to an instance. Specifically, every instance of a

class contains a separate set of all the

instance fields of that class.

When a field is referenced in a member-access (§14.5.4) of the form E.M,

if M is a static field, E must denote a

type that has a field M, and if M is an instance field, E must denote an

instance of a type that has a field M.

The differences between static and instance members are discussed further

in §17.2.5.

17.4.2 Readonly fields

When a field-declaration includes a readonly modifier, the fields

introduced by the declaration are readonly

fields. Direct assignments to readonly fields can only occur as part of

that declaration or in an instance

constructor or static constructor in the same class. (A readonly field can

be assigned to multiple times in these

contexts.) Specifically, direct assignments to a readonly field are

permitted only in the following contexts:

? In the variable-declarator that introduces the field (by including a

variable-initializer in the declaration).

? For an instance field, in the instance constructors of the class that

contains the field declaration; for a static

field, in the static constructor of the class that contains the field

declaration. These are also the only contexts

in which it is valid to pass a readonly field as an out or ref parameter.

Attempting to assign to a readonly field or pass it as an out or ref

parameter in any other context is a

compile-time error.

17.4.2.1 Using static readonly fields for constants

A static readonly field is useful when a symbolic name for a constant value

is desired, but when the type of

the value is not permitted in a const declaration, or when the value cannot

be computed at compile-time.

[Example: In the example

public class Color

{

public static readonly Color Black = new Color(0, 0, 0);

public static readonly Color White = new Color(255, 255, 255);

public static readonly Color Red = new Color(255, 0, 0);

public static readonly Color Green = new Color(0, 255, 0);

public static readonly Color Blue = new Color(0, 0, 255);

private byte red, green, blue;

public Color(byte r, byte g, byte b) {

red = r;

green = g;

blue = b;

}

}

the Black, White, Red, Green, and Blue members cannot be declared as const

members because their values

cannot be computed at compile-time. However, declaring them static readonly

instead has much the same

effect. end example]

17.4.2.2 Versioning of constants and static readonly fields

Constants and readonly fields have different binary versioning semantics.

When an expression references a

constant, the value of the constant is obtained at compile-time, but when

an expression references a readonly

field, the value of the field is not obtained until run-time. [Example:

Consider an application that consists of two

separate programs:

Chapter 17 Classes

223

using System;

namespace Program1

{

public class Utils

{

public static readonly int X = 1;

}

}

namespace Program2

{

class Test

{

static void Main() {

Console.WriteLine(Program1.Utils.X);

}

}

}

The Program1 and Program2 namespaces denote two programs that are compiled

separately. Because

Program1.Utils.X is declared as a static readonly field, the value output

by the Console.WriteLine

statement is not known at compile-time, but rather is obtained at run-time.

Thus, if the value of X is changed and

Program1 is recompiled, the Console.WriteLine statement will output the new

value even if Program2 isn?t

recompiled. However, had X been a constant, the value of X would have been

obtained at the time Program2 was

compiled, and would remain unaffected by changes in Program1 until Program2

is recompiled. end example]

17.4.3 Volatile fields

When a field-declaration includes a volatile modifier, the fields

introduced by that declaration are volatile

fields. For non-volatile fields, optimization techniques that reorder

instructions can lead to unexpected and

unpredictable results in multi-threaded programs that access fields without

synchronization such as that provided

by the lock-statement (§15.12). These optimizations can be performed by

the compiler, by the runtime system, or

by hardware. For volatile fields, such reordering optimizations are

restricted:

? A read of a volatile field is called a volatile read. A volatile read has

?acquire semantics?; that is, it is

guaranteed to occur prior to any references to memory that occur after it

in the instruction sequence.

? A write of a volatile field is called a volatile write. A volatile write

has ?release semantics?; that is, it is

guaranteed to happen after any memory references prior to the write

instruction in the instruction sequence.

These restrictions ensure that all threads will observe volatile writes

performed by any other thread in the order in

which they were performed. A conforming implementation is not required to

provide a single total ordering of

volatile writes as seen from all threads of execution. The type of a

volatile field must be one of the following:

? A reference-type.

? The type byte, sbyte, short, ushort, int, uint, char, float, or bool.

? An enum-type having an enum base type of byte, sbyte, short, ushort, int,

or uint.

[Example: The example

using System;

using System.Threading;

class Test

{

public static int result;

public static volatile bool finished;

static void Thread2() {

result = 143;

finished = true;

}

C# LANGUAGE SPECIFICATION

224

static void Main() {

finished = false;

// Run Thread2() in a new thread

new Thread(new ThreadStart(Thread2)).Start();

// Wait for Thread2 to signal that it has a result by setting

// finished to true.

for (;;) {

if (finished) {

Console.WriteLine("result = {0}", result);

return;

}

}

}

}

produces the output:

result = 143

In this example, the method Main starts a new thread that runs the method

Thread2. This method stores a value

into a non-volatile field called result, then stores true in the volatile

field finished. The main thread waits

for the field finished to be set to true, then reads the field result.

Since finished has been declared

volatile, the main thread must read the value 143 from the field result. If

the field finished had not been

declared volatile, then it would be permissible for the store to result to

be visible to the main thread after

the store to finished, and hence for the main thread to read the value 0

from the field result. Declaring

finished as a volatile field prevents any such inconsistency. end example]

17.4.4 Field initialization

The initial value of a field, whether it be a static field or an instance

field, is the default value (§12.2) of the

field?s type. It is not possible to observe the value of a field before

this default initialization has occurred, and a

field is thus never ?uninitialized?. [Example: The example

using System;

class Test

{

static bool b;

int i;

static void Main() {

Test t = new Test();

Console.WriteLine("b = {0}, i = {1}", b, t.i);

}

}

produces the output

b = False, i = 0

because b and i are both automatically initialized to default values. end

example]

17.4.5 Variable initializers

Field declarations may include variable-initializers. For static fields,

variable initializers correspond to

assignment statements that are executed during class initialization. For

instance fields, variable initializers

correspond to assignment statements that are executed when an instance of

the class is created.

[Example: The example

using System;

class Test

{

static double x = Math.Sqrt(2.0);

int i = 100;

string s = "Hello";

Chapter 17 Classes

225

static void Main() {

Test a = new Test();

Console.WriteLine("x = {0}, i = {1}, s = {2}", x, a.i, a.s);

}

}

produces the output

x = 1.4142135623731, i = 100, s = Hello

because an assignment to x occurs when static field initializers execute

and assignments to i and s occur when

the instance field initializers execute. end example]

The default value initialization described in §17.4.3 occurs for all

fields, including fields that have variable

initializers. Thus, when a class is initialized, all static fields in that

class are first initialized to their default values,

and then the static field initializers are executed in textual order.

Likewise, when an instance of a class is created,

all instance fields in that instance are first initialized to their default

values, and then the instance field initializers

are executed in textual order.

It is possible for static fields with variable initializers to be observed

in their default value state. [Example:

However, this is strongly discouraged as a matter of style. The example

using System;

class Test

{

static int a = b + 1;

static int b = a + 1;

static void Main() {

Console.WriteLine("a = {0}, b = {1}", a, b);

}

}

exhibits this behavior. Despite the circular definitions of a and b, the

program is valid. It results in the output

a = 1, b = 2

because the static fields a and b are initialized to 0 (the default value

for int) before their initializers are

executed. When the initializer for a runs, the value of b is zero, and so a

is initialized to 1. When the initializer

for b runs, the value of a is already 1, and so b is initialized to 2. end

example]

17.4.5.1 Static field initialization

The static field variable initializers of a class correspond to a sequence

of assignments that are executed in the

textual order in which they appear in the class declaration. If a static

constructor (§17.11) exists in the class,

execution of the static field initializers occurs immediately prior to

executing that static constructor. Otherwise,

the static field initializers are executed at an implementation-dependent

time prior to the first use of a static field

of that class. [Example: The example

using System;

class Test

{

static void Main() {

Console.WriteLine("{0} {1}", B.Y, A.X);

}

public static int f(string s) {

Console.WriteLine(s);

return 1;

}

}

class A

{

public static int X = Test.f("Init A");

}

C# LANGUAGE SPECIFICATION

226

class B

{

public static int Y = Test.f("Init B");

}

might produce either the output:

Init A

Init B

1 1

or the output:

Init B

Init A

1 1

because the execution of X’s initializer and Y’s initializer could occur

in either order; they are only constrained to

occur before the references to those fields. However, in the example:

using System;

class Test

{

static void Main() {

Console.WriteLine("{0} {1}", B.Y, A.X);

}

public static int f(string s) {

Console.WriteLine(s);

return 1;

}

}

class A

{

static A() {}

public static int X = Test.f("Init A");

}

class B

{

static B() {}

public static int Y = Test.f("Init B");

}

the output must be:

Init B

Init A

1 1

because the rules for when static constructors execute provide that B’s

static constructor (and hence B’s static field

initializers) must run before A’s static constructor and field

initializers. end example]

17.4.5.2 Instance field initialization

The instance field variable initializers of a class correspond to a

sequence of assignments that are executed

immediately upon entry to any one of the instance constructors (§17.10.2)

of that class. The variable initializers

are executed in the textual order in which they appear in the class

declaration. The class instance creation and

initialization process is described further in §17.10.

A variable initializer for an instance field cannot reference the instance

being created. Thus, it is a compile-time

error to reference this in a variable initializer, as it is a compile-time

error for a variable initializer to reference

any instance member through a simple-name. [Example: In the example

class A

{

int x = 1;

int y = x + 1; // Error, reference to instance member of this

}

Chapter 17 Classes

227

the variable initializer for y results in a compile-time error because it

references a member of the instance being

created. end example]

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有