.Net Basic

This blogs gives introduction to C#.NET programming for beginners. This blogs assumes that you have no programming experience whatsoever. It's a lot easier than you think, and can be a very rewarding hobby!after Refer this blog

20 June 2008

Variables in C#.net

Variables

Variables represent storage locations. Every variable has a type that determines what values can be stored in the variable. C# is a type-safe language, and the C# compiler guarantees that values stored in variables are always of the appropriate type. The value of a variable can be changed through assignment or through use of the ++ and ‑‑ operators.

A variable must be definitely assigned (§5.3) before its value can be obtained.

As described in the following sections, variables are either initially assigned or initially unassigned. An initially assigned variable has a well-defined initial value and is always considered definitely assigned. An initially unassigned variable has no initial value. For an initially unassigned variable to be considered definitely assigned at a certain location, an assignment to the variable must occur in every possible execution path leading to that location.
1.1 Variable categories

C# defines seven categories of variables: static variables, instance variables, array elements, value parameters, reference parameters, output parameters, and local variables. The sections that follow describe each of these categories.

In the example

class A
{
public static int x;
int y;

void F(int[] v, int a, ref int b, out int c) {
int i = 1;
c = a + b++;
}
}

x is a static variable, y is an instance variable, v[0] is an array element, a is a value parameter, b is a reference parameter, c is an output parameter, and i is a local variable.
1.1.1 Static variables

A field declared with the static modifier is called a static variable. A static variable comes into existence before execution of the static constructor (§10.12) for its containing type, and ceases to exist when the associated application domain ceases to exist.

The initial value of a static variable is the default value (§5.2) of the variable’s type.

For purposes of definite assignment checking, a static variable is considered initially assigned.
1.1.2 Instance variables

A field declared without the static modifier is called an instance variable.
1.1.2.1 Instance variables in classes

An instance variable of a class comes into existence when a new instance of that class is created, and ceases to exist when there are no references to that instance and the instance’s destructor (if any) has executed.

The initial value of an instance variable of a class is the default value (§5.2) of the variable’s type.

For the purpose of definite assignment checking, an instance variable of a class is considered initially assigned.
1.1.2.2 Instance variables in structs

An instance variable of a struct has exactly the same lifetime as the struct variable to which it belongs. In other words, when a variable of a struct type comes into existence or ceases to exist, so too do the instance variables of the struct.

The initial assignment state of an instance variable of a struct is the same as that of the containing struct variable. In other words, when a struct variable is considered initially assigned, so too are its instance variables, and when a struct variable is considered initially unassigned, its instance variables are likewise unassigned.
1.1.3 Array elements

The elements of an array come into existence when an array instance is created, and cease to exist when there are no references to that array instance.

The initial value of each of the elements of an array is the default value (§5.2) of the type of the array elements.

For the purpose of definite assignment checking, an array element is considered initially assigned.
1.1.4 Value parameters

A parameter declared without a ref or out modifier is a value parameter.

A value parameter comes into existence upon invocation of the function member (method, instance constructor, accessor, or operator) or anonymous function to which the parameter belongs, and is initialized with the value of the argument given in the invocation. A value parameter normally ceases to exist upon return of the function member or anonymous function. However, if the value parameter is captured by an anonymous function (§7.14), its life time extends at least until the delegate or expression tree created from that anonymous function is eligible for garbage collection.

For the purpose of definite assignment checking, a value parameter is considered initially assigned.
1.1.5 Reference parameters

A parameter declared with a ref modifier is a reference parameter.

A reference parameter does not create a new storage location. Instead, a reference parameter represents the same storage location as the variable given as the argument in the function member or anonymous function invocation. Thus, the value of a reference parameter is always the same as the underlying variable.

The following definite assignment rules apply to reference parameters. Note the different rules for output parameters described in §5.1.6.

· A variable must be definitely assigned (§5.3) before it can be passed as a reference parameter in a function member or delegate invocation.

· Within a function member or anonymous function, a reference parameter is considered initially assigned.

Within an instance method or instance accessor of a struct type, the this keyword behaves exactly as a reference parameter of the struct type (§7.5.7).
1.1.6 Output parameters

A parameter declared with an out modifier is an output parameter.

An output parameter does not create a new storage location. Instead, an output parameter represents the same storage location as the variable given as the argument in the function member or delegate invocation. Thus, the value of an output parameter is always the same as the underlying variable.

The following definite assignment rules apply to output parameters. Note the different rules for reference parameters described in §5.1.5.

· A variable need not be definitely assigned before it can be passed as an output parameter in a function member or delegate invocation.

· Following the normal completion of a function member or delegate invocation, each variable that was passed as an output parameter is considered assigned in that execution path.

· Within a function member or anonymous function, an output parameter is considered initially unassigned.

· Every output parameter of a function member or anonymous function must be definitely assigned (§5.3) before the function member or anonymous function returns normally.

Within an instance constructor of a struct type, the this keyword behaves exactly as an output parameter of the struct type (§7.5.7).
1.1.7 Local variables

A local variable is declared by a local-variable-declaration, which may occur in a block, a for-statement, a switch-statement or a using-statement; or by a foreach-statement or a specific-catch-clause for a try-statement.

The lifetime of a local variable is the portion of program execution during which storage is guaranteed to be reserved for it. This lifetime extends at least from entry into the block, for-statement, switch-statement, using-statement, foreach-statement, or specific-catch-clause with which it is associated, until execution of that block, for-statement, switch-statement, using-statement, foreach-statement, or specific-catch-clause ends in any way. (Entering an enclosed block or calling a method suspends, but does not end, execution of the current block, for-statement, switch-statement, using-statement, foreach-statement, or specific-catch-clause.) If the local variable is captured by an anonymous function (§7.14.4.1), its lifetime extends at least until the delegate or expression tree created from the anonymous function, along with any other objects that come to reference the captured variable, are eligible for garbage collection.

If the parent block, for-statement, switch-statement, using-statement, foreach-statement, or specific-catch-clause is entered recursively, a new instance of the local variable is created each time, and its local-variable-initializer, if any, is evaluated each time.

A local variable introduced by a local-variable-declaration is not automatically initialized and thus has no default value. For the purpose of definite assignment checking, a local variable introduced by a local-variable-declaration is considered initially unassigned. A local-variable-declaration may include a local-variable-initializer, in which case the variable is considered definitely assigned in its entire scope, except within the expression provided in the local-variable-initializer.

Within the scope of a local variableintroduced by a local-variable-declaration, it is a compile-time error to refer to that local variable in a textual position that precedes its local-variable-declarator. If the local variable declaration is implicit (§8.5.1), it is also an error to refer to the variable within its local-variable-declarator.

A local variable introduced by a foreach-statement or a specific-catch-clause is considered definitely assigned in its entire scope.

The actual lifetime of a local variable is implementation-dependent. For example, a compiler might statically determine that a local variable in a block is only used for a small portion of that block. Using this analysis, the compiler could generate code that results in the variable’s storage having a shorter lifetime than its containing block.

The storage referred to by a local reference variable is reclaimed independently of the lifetime of that local reference variable (§3.9).
1.2 Default values

The following categories of variables are automatically initialized to their default values:

· Static variables.

· Instance variables of class instances.

· Array elements.

The default value of a variable depends on the type of the variable and is determined as follows:

· For a variable of a value-type, the default value is the same as the value computed by the value-type’s default constructor (§4.1.2).

· For a variable of a reference-type, the default value is null.

Initialization to default values is typically done by having the memory manager or garbage collector initialize memory to all-bits-zero before it is allocated for use. For this reason, it is convenient to use all-bits-zero to represent the null reference.
1.3 Definite assignment

At a given location in the executable code of a function member, a variable is said to be definitely assigned if the compiler can prove, by a particular static flow analysis (§5.3.3), that the variable has been automatically initialized or has been the target of at least one assignment. Informally stated, the rules of definite assignment are:

· An initially assigned variable (§5.3.1) is always considered definitely assigned.

· An initially unassigned variable (§5.3.2) is considered definitely assigned at a given location if all possible execution paths leading to that location contain at least one of the following:

o A simple assignment (§7.16.1) in which the variable is the left operand.

o An invocation expression (§7.5.5) or object creation expression (§7.5.10.1) that passes the variable as an output parameter.

o For a local variable, a local variable declaration (§8.5.1) that includes a variable initializer.

The formal specification underlying the above informal rules is described in §5.3.1, §5.3.2, and §5.3.3.

The definite assignment states of instance variables of a struct-type variable are tracked individually as well as collectively. In additional to the rules above, the following rules apply to struct-type variables and their instance variables:

· An instance variable is considered definitely assigned if its containing struct-type variable is considered definitely assigned.

· A struct-type variable is considered definitely assigned if each of its instance variables is considered definitely assigned.

Definite assignment is a requirement in the following contexts:

· A variable must be definitely assigned at each location where its value is obtained. This ensures that undefined values never occur. The occurrence of a variable in an expression is considered to obtain the value of the variable, except when

o the variable is the left operand of a simple assignment,

o the variable is passed as an output parameter, or

o the variable is a struct-type variable and occurs as the left operand of a member access.

· A variable must be definitely assigned at each location where it is passed as a reference parameter. This ensures that the function member being invoked can consider the reference parameter initially assigned.

· All output parameters of a function member must be definitely assigned at each location where the function member returns (through a return statement or through execution reaching the end of the function member body). This ensures that function members do not return undefined values in output parameters, thus enabling the compiler to consider a function member invocation that takes a variable as an output parameter equivalent to an assignment to the variable.

· The this variable of a struct-type instance constructor must be definitely assigned at each location where that instance constructor returns.
1.3.1 Initially assigned variables

The following categories of variables are classified as initially assigned:

· Static variables.

· Instance variables of class instances.

· Instance variables of initially assigned struct variables.

· Array elements.

· Value parameters.

· Reference parameters.

· Variables declared in a catch clause or a foreach statement.
1.3.2 Initially unassigned variables

The following categories of variables are classified as initially unassigned:

· Instance variables of initially unassigned struct variables.

· Output parameters, including the this variable of struct instance constructors.

· Local variables, except those declared in a catch clause or a foreach statement.
1.3.3 Precise rules for determining definite assignment

In order to determine that each used variable is definitely assigned, the compiler must use a process that is equivalent to the one described in this section.

The compiler processes the body of each function member that has one or more initially unassigned variables. For each initially unassigned variable v, the compiler determines a definite assignment state for v at each of the following points in the function member:

· At the beginning of each statement

· At the end point (§8.1) of each statement

· On each arc which transfers control to another statement or to the end point of a statement

· At the beginning of each expression

· At the end of each expression

The definite assignment state of v can be either:

· Definitely assigned. This indicates that on all possible control flows to this point, v has been assigned a value.

· Not definitely assigned. For the state of a variable at the end of an expression of type bool, the state of a variable that isn’t definitely assigned may (but doesn’t necessarily) fall into one of the following sub-states:

o Definitely assigned after true expression. This state indicates that v is definitely assigned if the boolean expression evaluated as true, but is not necessarily assigned if the boolean expression evaluated as false.

o Definitely assigned after false expression. This state indicates that v is definitely assigned if the boolean expression evaluated as false, but is not necessarily assigned if the boolean expression evaluated as true.

Labels:

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home