Home Random Page


CATEGORIES:

BiologyChemistryConstructionCultureEcologyEconomyElectronicsFinanceGeographyHistoryInformaticsLawMathematicsMechanicsMedicineOtherPedagogyPhilosophyPhysicsPolicyPsychologySociologySportTourism






Nbsp;   Adding Methods to Enumerated Types

Earlier in this chapter, I mentioned that you cannot define a method as part of an enumerated type. And, for many years, this has saddened me because there are many occasions when I would love to have been able to supply some methods to my enumerated type. Fortunately, I can use C#’s exten- sion method feature (discussed in Chapter 8, “Methods”) to simulate adding methods to an enumer- ated type.

If I want to add some methods to the FileAttributes enumerated type, I can define a static

class with extension methods as follows.

 

internal static class FileAttributesExtensionMethods {

public static Boolean IsSet(this FileAttributes flags, FileAttributes flagToTest) { if (flagToTest == 0)

throw new ArgumentOutOfRangeException("flagToTest", "Value must not be 0"); return (flags & flagToTest) == flagToTest;

}

 

public static Boolean IsClear(this FileAttributes flags, FileAttributes flagToTest) { if (flagToTest == 0)

throw new ArgumentOutOfRangeException("flagToTest", "Value must not be 0"); return !IsSet(flags, flagToTest);

}

 

public static Boolean AnyFlagsSet(this FileAttributes flags, FileAttributes testFlags) { return ((flags & testFlags) != 0);

}

 

public static FileAttributes Set(this FileAttributes flags, FileAttributes setFlags) { return flags | setFlags;

}


public static FileAttributes Clear(this FileAttributes flags, FileAttributes clearFlags) {

return flags & ~clearFlags;

}

 

public static void ForEach(this FileAttributes flags, Action<FileAttributes> processFlag) {

if (processFlag == null) throw new ArgumentNullException("processFlag"); for (UInt32 bit = 1; bit != 0; bit <<= 1) {

UInt32 temp = ((UInt32)flags) & bit;

if (temp != 0) processFlag((FileAttributes)temp);

}

}

}

 

And here is some code that demonstrates calling some of these methods. As you can see, the code looks as if I’m calling methods on the enumerated type.

 

FileAttributes fa = FileAttributes.System; fa = fa.Set(FileAttributes.ReadOnly);

fa = fa.Clear(FileAttributes.System); fa.ForEach(f => Console.WriteLine(f));


C HA P T E R 1 6

Arrays

In this chapter:

Initializing Array Elements....................................................................... 376

Casting Arrays......................................................................................... 378

All Arrays Are Implicitly Derived fromSystem.Array........................ 380

All Arrays Implicitly ImplementIEnumerable,

ICollection, andIList................................................................ 381

Passing and Returning Arrays................................................................... 382

Creating Non-Zero Lower Bound Arrays................................................... 383

Array Internals........................................................................................ 384



Unsafe Array Access and Fixed-Size Array................................................ 388

 

Arrays are mechanisms that allow you to treat several items as a single collection. The Microsoft

.NET common language runtime (CLR) supports single-dimensional arrays, multi-dimensional arrays, and jagged arrays (that is, arrays of arrays). All array types are implicitly derived from the System.Array abstract class, which itself is derived from System.Object. This means that arrays are always reference types that are allocated on the managed heap and that your application’s vari- able or field contains a reference to the array and not the elements of the array itself. The following code makes this clearer.

 

Int32[] myIntegers; // Declares a reference to an array myIntegers = new Int32[100]; // Creates an array of 100 Int32s

 

On the first line, myIntegers is a variable that’s capable of pointing to a single-dimensional array of Int32s. Initially, myIntegers will be set to null because I haven’t allocated an array. The second line of code allocates an array of 100 Int32 values; all of the Int32s are initialized to 0. Because arrays are reference types, the memory block required to hold the 100 unboxed Int32s is allocated on the managed heap. Actually, in addition to the array’s elements, the memory block occupied by an array object also contains a type object pointer, a sync block index, and some additional over- head members as well. The address of this array’s memory block is returned and saved in the variable myIntegers.

You can also create arrays of reference types.

 

Control[] myControls; // Declares a reference to an array myControls = new Control[50]; // Creates an array of 50 Control references


On the first line, myControls is a variable capable of pointing to a single-dimensional array of Control references. Initially, myControls will be set to null because I haven’t allocated an array. The second line allocates an array of 50 Control references; all of these references are initialized to null. Because Control is a reference type, creating the array creates only a bunch of references; the actual objects aren’t created at this time. The address of this memory block is returned and saved in the variable myControls.

Figure 16-1 shows how arrays of value types and arrays of reference types look in the managed heap.

 

 

       
   
 

 

FIGURE 16-1Arrays of value and reference types in the managed heap.

 

In the figure, the Controls array shows the result after the following lines have executed.

 

myControls[1] = new Button(); myControls[2] = new TextBox();

myControls[3] = myControls[2]; // Two elements refer to the same object. myControls[46] = new DataGrid();

myControls[48] = new ComboBox(); myControls[49] = new Button();

 

Common Language Specification (CLS) compliance requires all arrays to be zero-based. This allows a method written in C# to create an array and pass the array’s reference to code written in another language, such as Microsoft Visual Basic .NET. In addition, because zero-based arrays are, by far, the most common arrays, Microsoft has spent a lot of time optimizing their performance. However, the CLR does support non-zero–based arrays even though their use is discouraged. For those of you who don’t care about a slight performance penalty or cross-language portability, I’ll demonstrate how to create and use non-zero–based arrays later in this chapter.

Notice in Figure 16-1 that each array has some additional overhead information associated with it. This information contains the rank of the array (number of dimensions), the lower bounds for each di- mension of the array (almost always 0), and the length of each dimension. The overhead also contains


the array’s element type. I’ll mention the methods that allow you to query this overhead information later in this chapter.

So far, I’ve shown examples demonstrating how to create single-dimensional arrays. When pos- sible, you should stick with single-dimensional, zero-based arrays, sometimes referred to as SZ arrays, or vectors. Vectors give the best performance because you can use specific Intermediate Language (IL) instructions—such as newarr, ldelem, ldelema, ldlen, and stelem—to manipulate them.

However, if you prefer to work with multi-dimensional arrays, you can. Here are some examples of multi-dimensional arrays.

 

// Create a two­dimensional array of Doubles. Double[,] myDoubles = new Double[10, 20];

 

// Create a three­dimensional array of String references. String[,,] myStrings = new String[5, 3, 10];

 

The CLR also supports jagged arrays, which are arrays of arrays. Zero-based, single-dimensional jagged arrays have the same performance as normal vectors. However, accessing the elements of a jagged array means that two or more array accesses must occur. Here are some examples of how to create an array of polygons with each polygon consisting of an array of Point instances.

 

// Create a single­dimensional array of Point arrays. Point[][] myPolygons = new Point[3][];

 

// myPolygons[0] refers to an array of 10 Point instances. myPolygons[0] = new Point[10];

 

// myPolygons[1] refers to an array of 20 Point instances. myPolygons[1] = new Point[20];

 

// myPolygons[2] refers to an array of 30 Point instances. myPolygons[2] = new Point[30];

 

// Display the Points in the first polygon.

for (Int32 x = 0; x < myPolygons[0].Length; x++) Console.WriteLine(myPolygons[0][x]);

       
   
 
 



Date: 2016-03-03; view: 712


<== previous page | next page ==>
Nbsp;   Bit Flags | Nbsp;   Initializing Array Elements
doclecture.net - lectures - 2014-2024 year. Copyright infringement or personal data (0.008 sec.)