Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Daniel Solis - Illustrated C# 2010 - 2010.pdf
Скачиваний:
16
Добавлен:
11.06.2015
Размер:
11.23 Mб
Скачать

CHAPTER 25 OTHER TOPICS

More About the Nullable Types

In Chapter 3 you got an introduction to nullable types. As you’ll remember, nullable types allow you to create a value type variable that can be marked as valid or invalid, effectively letting you set a value type variable to “null.” I wanted to introduce nullable types in Chapter 3 with the other built-in types, but now that you know more about C#, it’s a good time to cover their more intricate aspects.

Just to review, a nullable type is always based on another type, called the underlying type, that has already been declared.

You can create a nullable type from any value type, including the predefined, simple types.

You cannot create a nullable type from a reference type or another nullable type.

You do not explicitly declare a nullable type in your code. Instead, you declare a variable of a nullable type. The compiler implicitly creates the nullable type for you.

To create a variable of a nullable type, simply add a question mark to the end of the name of the underlying type, in the variable declaration.

For example, the following code declares a variable of the nullable int type. Notice that the suffix is attached to the type name—not the variable name.

Suffix

int? myNInt = 28;

The name of the nullable type includes the suffix.

With this declaration statement, the compiler takes care of both producing the nullable type and the variable of that type. Figure 25-3 shows the structure of this nullable type. It contains the following:

An instance of the underlying type

Several important read-only properties:

Property HasValue is of type bool and indicates whether the value is valid.

Property Value is the same type as the underlying type and returns the value of the variable— if the variable is valid.

Figure 25-3. A nullable type contains an object of the underlying type in a struct, with two read-only

properties.

674

CHAPTER 25 OTHER TOPICS

You can use the two read-only properties explicitly as follows. Reading a variable of a nullable type returns its value. You must, however, make sure that the variable is not null. Attempting to read the value of a null variable produces an exception.

int? myInt1 = 15;

Explicitly use the property.

if (myInt1.HasValue ) Console.WriteLine("{0}", myInt1.Value);

Explicitly use the property.

A better method, however, is to use the shortcut forms, as shown in the following code.

To check whether a nullable type has a value, you can compare it to null.

Like any variable, to retrieve its value, you can just use its name.

Compare to null

if ( myInt1 != null ) Console.WriteLine("{0}", myInt1);

Use variable name

Both sets of code produce the following output:

15

675

CHAPTER 25 OTHER TOPICS

The Null Coalescing Operator

The standard arithmetic and comparison operators also handle nullable types. There is also a special operator called the null coalescing operator, which returns a non-null value to an expression, in case a nullable type variable is null.

The null coalescing operator consists of two contiguous question marks and has two operands:

The first operand is a variable of a nullable type.

The second is a non-nullable value of the same underlying type.

If, at run time, the first operand evaluates to null, the second operand is returned as the result of the operation.

Null coalescing operator int? myI4 = null; Console.WriteLine("myI4: {0}", myI4 ?? -1);

myI4 = 10;

Console.WriteLine("myI4: {0}", myI4 ?? -1);

This code produces the following output:

myI4: -1 myI4: 10

The equality comparison operators, == and !=, have an interesting characteristic you need to be aware of. If you compare two values of the same nullable type and both are null, the equality comparison operators consider them equal. For example, in the following code, the two nullable ints are set to null. The equality comparison operator declares them equal.

int? i1 =

null, i2 = null;

//

Both are

null.

if (i1 ==

i2)

//

Operator

returns true.

Console.WriteLine("Equal");

 

 

 

676

CHAPTER 25 OTHER TOPICS

Using Nullable User-Defined Types

So far, you’ve seen nullable forms of the predefined, simple types. You can also create nullable forms of user-defined value types. These bring up additional issues that don’t come up when using the simple types.

The main issue is access to the members of the encapsulated underlying type. A nullable type doesn’t directly expose any of the members of the underlying type. For example, take a look at the following code and its representation in Figure 25-4. The code declares a struct (which is a value type) called MyStruct, with two public fields.

Since the fields of the struct are public, they can easily be accessed in any instance of the struct, as shown on the left of the figure.

The nullable version of the struct, however, exposes the underlying type only through the Value property and doesn’t directly expose any of its members. Although the members are public to the struct, they are not public to the nullable type, as shown on the right of the figure.

struct MyStruct

// Declare a struct.

{

 

public int X;

// Field

public int Y;

// Field

public MyStruct(int xVal, int yVal)

// Constructor

{ X = xVal; Y = yVal; }

 

}

 

class Program {

 

static void Main()

 

{

 

MyStruct? mSNull = new MyStruct(5, 10);

...

Figure 25-4. The accessibility of the members of a struct is different from that of the nullable type.

677

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]