Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

CSharp Bible (2002) [eng]-1

.pdf
Скачиваний:
42
Добавлен:
16.08.2013
Размер:
4.29 Mб
Скачать

If you try to redefine the type of an identifier within the same code block, the C# compiler issues an error message, as demonstrated by the following code:

public static void Main()

{

int MyVariable = 123; float MyVariable = 1.25;

}

The C# compiler issues an error message at the line that tries to redefine MyVariable as a float value:

error CS0128: A local variable named 'MyVariable' is already defined in this scope

You can, however, reuse the identifier if it appears in a separate code block:

public static void Main()

{

int MyVariable = 123;

}

public void AnotherFunction()

{

float MyVariable = 1.25;

}

Understanding parenthesized expressions

As their name suggests, parenthesized expressions are expressions enclosed in parentheses. The C# compiler evaluates the expression inside the parentheses, and the value of the parenthesized expression is the result of the evaluation. For example, the value of the parenthesized expression (3+2) is 5.

Calling methods with member access expressions

When you need to call a method in an object, you write the object name, followed by a period, followed by the name of the method. When the CLR calls your Main() method to begin running your application, it creates an object from your class and calls the Main() function on that object. If you were to write this code in C#, you might write something like the following:

MyClass MyObject;

MyObject = new MyClass();

MyObject.Main();

Objects are covered in detail in Chapters 8 and 9. The important item to note now is that the statement that calls Main() contains a member access expression, which contains an object, a period, and a function call.

In later chapters, you see that objects can have data as well as code. You can access the data by using the same member access expression syntax.

Calling methods with invocation expressions

You use invocation expressions to make a call to a method in an object. The code used in the member access case also shows an invocation expression. The code calls a method — Main(), in this case — which causes the code to invoke the Main() method on the object.

If you call a method from another method on the same object, you can use the name of the method in the call. You do not need to specify an object or class name, and the member access syntax is not necessary, as shown in Listing 4-1.

Listing 4-1: Invocation Expression

class MyClass

{

public static void Main()

{

MyClass myclass = new MyClass(); myclass.DoWork();

}

void DoWork()

{

// do work here

}

}

In this example, the Main() method calls a DoWork() method. However, first you need to create a reference to myClass and then invoke the DoWork() method.

The type of an invocation expression is the type returned by the function being called. If, for example, your C# code calls a function that returns an int type, the invocation expression that calls that method has a type of int.

Specifying array elements with element access expressions

Element access expressions enable you to specify array elements. You write the array element number within square brackets:

int [] MyArray;

MyArray = new int [5];

MyArray[0] = 123;

In this example, element zero of the array named MyArray is assigned a value of 123.

C# allows any expression resulting in type int, uint, long, or ulong to be used as the element expression. C# also allows the use of any expression whose result is of a type that can be implicitly converted into an int, uint, long, or ulong type. In the preceding code, an integer literal is used as the element expression. You could just as easily write a different kind of expression to specify the element, as shown in Listing 4-2.

Listing 4-2: Element Access

class MyClass

{

public static void Main()

{

int [] MyArray;

MyClass myclass = new MyClass(); MyArray = new int [5]; MyArray[myclass.GetArrayIndex()] = 123;

}

int GetArrayIndex()

{

return 0;

}

}

This code works because the GetArrayIndex() method returns an int, and the result of the method invocation expression is an int. Because any expression whose value is an int can be used as an array element expression, C# allows this code to execute.

The result of the element access expression itself is the type of the element being accessed, as shown in the following code:

int [] MyArray;

MyArray = new int [5];

MyArray[0] = 123;

The MyArray[0] element access expression is of type int because the element being accessed in the expression is of type int.

Accessing objects with the this keyword

C# defines a this keyword that you can use to specify an object to a piece of code that needs access to that object. The this keyword is covered in more detail in the section that takes a look at classes. Listing 4-3 uses the this keyword.

Listing 4-3: Keyword Access

class MyClass

{

public static void Main()

{

// call DoWork() on this object MyClass myclass = new MyClass(); myclass.DoWork();

}

void DoWork()

{

MyClass myclass = new MyClass(); this.DoWork2();

// do work here

}

void DoWork2()

{

}

}

In this example, the this access expression has a type of MyClass because the MyClass class contains the code that contains the this access expression.

Accessing objects with the base keyword

C# also defines the base keyword for use with objects. In Chapter 8, you learn that you can use classes as a starting point to construct new classes. The original classes are called base classes, and the classes constructed from them are called derived classes.

To instruct your C# code in derived classes to access data in base classes, use the base keyword. The type for expressions using the base is the base class of the class containing the base keyword.

Using postfix increment and decrement operators

C# enables you to increment or decrement numeric values using special symbols. The ++ operator increments the value, and the -- operator decrements the value. You can apply these operators to expressions of type sbyte, byte, short, ushort, int, uint, long, and ulong. Listing 4- 4 illustrates the increment and decrement operators in use.

Listing 4-4: Increment and Decrement Operators

class MyClass

{

public static void Main()

{

int MyInteger;

MyInteger = 125;

MyInteger++; // value is now 126 MyInteger--; // value is now back to 125

}

}

The type of an expression using the postfix increment and decrement operators matches the type whose value is being incremented or decremented. In Listing 4-4, the increment and decrement operators have a type of int.

Creating new reference types with the new operator

You use the new operator to create new instances of reference types. So far, the new operator has been used to create new arrays, and when you look at objects, you learn how the new operator is used to create new objects.

The new operator is considered an expression, and the type of the expression matches the type of variable being created with the new keyword.

Returning type information with the typeof operator

The typeof operator is a C# keyword that returns information about a type of a variable. You use it as if it were a function, using the typeof keyword and following it with an expression:

class MyClass

{

public static void Main()

{

System.Console.WriteLine(typeof(int));

}

}

The typeof keyword returns an object called System.Type describing the variable's type. The type of a typeof expression is the System.Type class.

Using the checked and unchecked operators

With the checked and unchecked operators, you can enable or disable runtime checking of your mathematical operations. If you include a mathematical operation in a checked operator, an error is reported if the operation doesn't make sense. If you include a mathematical operation in an unchecked operator, an error is reported even if the operation doesn't make sense.

Listing 4-5 demonstrates a mathematical overflow problem. It declares two integers, Int1 and Int2, and a third, Int1PlusInt2, whose value stores the sum of the other two. The two integers are added together and the result of the addition is stored in the third integer variable. The value of the third variable is then printed to the console.

Listing 4-5: Overflow in Mathematical Operations

class Listing4_5

{

public static void Main()

{

int Int1; int Int2;

int Int1PlusInt2;

Int1 = 2000000000;

Int2 = 2000000000; Int1PlusInt2 = Int1 + Int2;

System.Console.WriteLine(Int1PlusInt2);

}

}

The Int1 and Int2 integers each are assigned a value of two billion. This is not a problem because integer variables can store values just above 2.1 billion. However, adding these two integers together and storing the result in another integer is going to be a problem. The sum will be four billion, which is larger than the maximum integer value of just over 2.1 billion.

Compile the preceding code with the standard command line:

csc Listing4-1.cs

When you run Listing 4-1.exe, you get a large negative number, as shown in Figure 4-1.

Figure 4-1: Overflows yield unpredictable results.

You get a negative number because of the way in which C# handles values that are too big to fit in the variables meant to hold them. C# couldn't represent the entire value in an integer, so it took the intended value, four billion, and subtracted the maximum value of a 32-bit value (4,294,967,296) from it, out putting the result to the console.

Obviously, your code has generated a result other than what you intended. If you're unaware of this sort of mathematical error, your code could behave unpredictably. To insert a measure of safety into code like this, you can use the checked operator, as shown in Listing 4-6.

Listing 4-6: Checking for Overflow in Mathematical Operations

class Listing4_6

{

public static void Main()

{

int Int1; int Int2;

int Int1PlusInt2;

Int1 = 2000000000;

Int2 = 2000000000;

Int1PlusInt2 = checked(Int1 + Int2); System.Console.WriteLine(Int1PlusInt2);

}

}

Compiling and running Listing 4-6 writes a different result to the console:

Exception occurred: System.OverflowException: An exception of

type System.OverflowException was thrown. at Listing4_1.Main()

Rather than writing a nonsensical mathematical value to the console, an overflow exception message lets you know that the value of the addition was checked for legality, and that the check failed the test. An exception is reported and the application terminates.

The unchecked() expression is the default case. Expressions marked with unchecked() are not checked for legal values, and the application continues running using the unchecked, nonsensical values.

The default behavior is not to check any operations. However, if you want to have all your operations checked for legal values without using the checked() operator in your code, you can use the /checked+ option to the compiler. Compile Listing 4-1 with the following command line:

csc /checked+ Listing4-1.cs

When you run the executable for Listing 4-1, you get the same exception message as you did with Listing 4-2, because the /checked+ option causes all mathematical operations to be checked for valid values.

Understanding Unary Expressions

Unary expressions operate on a single operand. C# supports the following unary expressions:

Unary plus operator

Unary minus operator

Logical negation operator

Bitwise complement operator

Indirection operator

Address operator

Prefix increment and decrement operators

Cast expressions

The following sections discuss these unary expressions in detail.

Returning operand values with the unary plus operator

The unary plus operator (+) returns the value of the operand. You can think of it as the mathematical positive operator. C# defines the unary plus operator for operands of type int, uint, long, ulong, float, double, and decimal.

Returning operand values with the unary minus operator

The unary minus operator (-) returns the value of the operand. You can think of it as the mathematical negative operator. The value of an operand with a unary minus operator is the operand's mathematical negative counterpart. C# defines the unary minus operator for operands of type int, long, float, double, and decimal.

Negating Boolean expressions with the logical negation operator

The logical negation operator negates the value of a Boolean expression. The operator changes True values to False, and changes False values to True.

Use the exclamation point to write a logical negation operator in your C# code. Place the operator before the Boolean expression you want to negate, as shown in Listing 4-7.

Listing 4-7: Logical Negation Operator

class MyClass

{

public static void Main()

{

bool MyBoolean;

MyBoolean = true;

MyBoolean = !MyBoolean; // "MyBoolean" now false

}

}

Understanding bitwise complement operator

C# enables you to apply a bitwise complement operation to int, uint, long, and ulong expressions. Bitwise complement operations view your value as if they are a binary, and flip all of the bits. Bits that had a value of 1 become 0, and bits that had a value of 0 become 1.

You specify bitwise complement operators by placing the tilde character (~) before the expression that should be bitwise complemented, as shown in Listing 4-8.

Listing 4-8: Bitwise Complement Operator

class MyClass

{

public static void Main()

{

int Int1;

Int1 = 123;

Int1 = ~Int1;

}

}

Prefixing increment and decrement operators

The postfix operators ++ and -- operators can be used in one of two ways. You've already looked at the postfix versions of the operators, which appear after the expression. The prefix versions appear before the expression, as shown in Listing 4-9.

Listing 4-9: Prefix Increment and Decrement Operators

class MyClass

{

public static void Main()

{

int MyInteger;

MyInteger = 125;

++MyInteger; // value is now 126 --MyInteger; // value is now back to 125

}

}

The type of an expression using the prefix increment and decrement operators matches the type whose value is being incremented or decremented.

Note the subtle difference between these prefix operators and the postfix operators discussed previously: With the prefix operators, the value is changed before the expression is evaluated. With the postfix operators, the value is changed after the expression is evaluated. Listing 4-10 illustrates this difference.

Listing 4-10: Differences Between Postfix and Prefix Operators

class Listing4_10

{

public static void Main()

{

int Int1;

Int1 = 123; System.Console.WriteLine(Int1++);

System.Console.WriteLine(++Int1);

}

}

Compile and run Listing 4-3. The output from this application is shown in Figure 4-2.

Figure 4-2: Postfix and prefix operator usage

The first statement in Listing 4-10 uses the postfix increment operator, which means that the value increments after the statement executes. The application writes the current value, 123, to the console and then increments the value to 124. The second statement uses the prefix increment operator, which means that the value is incremented before the statement executes. The application first increments the current value to 125 and then writes the current value to the console.

Understanding Arithmetic Operators

Arithmetic operators enable you to perform arithmetic in your C# code. Expressions that use arithmetic operators are binary expressions because two operands are required to perform a mathematical operation.

Assigning new values with the assignment operator

The assignment operator assigns a new value to a variable. The equals sign is used as the assignment operator:

MyInteger = 3;

The value of MyInteger is set to 3, and the previous value of MyVariable is lost.

Compound assignment operators enable you to use the assignment operator more than once in a statement:

MyInteger = MyOtherInteger = 3;

The value of the rightmost expression is used as the new value for the variables. In this example, both MyInteger and MyOtherInteger are given a new value of 3.

Using the multiplication operator

The value of an expression using the multiplication operator is the product of the values of the two operators. The asterisk character is used as the multiplication operator, as shown in Listing 4-11.

Listing 4-11: Multiplication Operator

class MyClass

{

public static void Main()

{

int MyInteger;

MyInteger = 3 * 6; // MyInteger will be 18

}

}

Соседние файлы в предмете Программирование на C++