Assemblies
The System .Reflection.Assembly class is important in much the same way as the Type class. Static Assembly methods load assemblies into the current application domain, and return an Assembly instance that describes the loaded assembly. An Assembly instance gives you access to the assembly's types and the assembly's resources. There are also static methods that reveal occasionally invaluable bits of information about the call stack, like GetExecutingAssembly, which returns the Assembly that...
Interfaces
Not reference counted, but otherwise only differ from Delphi in minor details Interfaces are types as are enums, classes, structs, and delegates and can be declared either as members of a namespace Chapter 9 or nested in a class. Interfaces can contain both method and property declarations. Like abstract method declarations, interface declarations have a semicolon instead of a method body. Classes can only inherit from a single base class in both C and Delphi Chapter 7 . However, in native code...
Tip If you are creating a form programmatically remember to add controls to the
The WinForms z-order design is a lot simpler than the VCL's multipass design. But the VCL asks a lot less of a form designer than WinForms does. Or something like that because, until recently, if you didn't create your docked controls in just the right order, your options were to either cut and paste controls in the form editor losing event handlers in the process or to edit the InitializeComponent source to change the order that you add controls to the container's Controls collection. In VS...
Note Remember when you set a field of an object instance you always put the
The first formal parameter, the int Value. Again, you have to keep track of which parameter has which number ILDASM misses its chance to annotate this as ldarg. 1 Value. IL_0002 stfld int32 testLibrary.testClass aField The first value on the stack is a reference ldarg .0 set the object's aField field to the second value ldarg.1 . These three instructions implement this.aField Value. The closing . Remember, the ret instruction can occur in more than one place. The comment here is another ILDASM...
String Conversions
Formatting and parsing n umbers and dates As you've already seen, the various overrides and overloads of the Object .ToString method are the FCL equivalent of Delphi's functions like IntToStr and IntToHex. A 'bare' ToString call gives the default format, which is generally the most compact format. Numbers and dates also support a ToString FormatString overload, which allows you to format values as in String.Format. That is, values are responsible for formatting themselves. Similarly, each...
Explicit Event Syntax
The second type of event declaration uses a more complex event syntax, with explicit add and remove methods event DelegateType EventName add add value remove remove value declares an event that even within its own object can only be accessed through the add and remove methods. That is, subscribe with or unsubscribe with - . Typically, this second type of event will be pretty straightforwardly mapped to a private delegate field public event EventType EventName EventType must be a delegate type...
Callback on Completion
Every delegate's Beginlnvoke method has two extra parameters after any Invoke parameters the first is an AsyncCallback delegate and the second is an arbitrary object. If the AsyncCallback delegate is non-null, the asynchronous mechanism will Invoke it synchronously in the same ThreadPool thread11 that runs the delegate see the Chapter8 AsynchTest project once the asynchronously invoked delegate returns. An AsyncCallback delegate takes a single parameter, which is the same IAsyncResult that...
The NET Memory Model
Hides the details of memory synchronization In native code on a single-processor machine, careful use of the various synchronization primitives is all that you need to build reliable multithreaded applications. However, multiprocessor systems can present special challenges, because each processor may have its own cache.12 If ThisThread 12. Hyperthreaded processors share cache, as do some not all multicore machines. has SomeVariable in its cache and then ThatThread changes SomeVariable, you want...
Waiting for Completion
If the asynchronous delegate has any side effects, other threads may want to wait for it to complete before doing anything that depends on those side effects. These threads can use WaitHandle methods Chapter 17 like the IAsyncResult.AsyncWaitHandle.WaitOne instance method or the static WaitHandle methods WaitAll and WaitAny to wait until the IAsyncResult. AsyncWaitHandle event is signaled. While you can call Beginlnvoke in one thread and call Endlnvoke in a different thread, this still allows...
NET Is Not Interpreted
Chapter 1 covered a number of important advantages of managed code No memory corruption from unchecked casts from unchecked array indexing from dangling references, aka tombstoned pointers or from pointer arithmetic. Managed code is easier to write than unmanaged code, because it doesn't need to be cluttered with memory management boilerplate, and because eliminating certain common types of errors means that you get your code working sooner. Managed code is easier to read than unmanaged code,...
Multithreading
Garbage collection suspends secondary threads In any heap system, whether manual or automatic, multithreaded programs have to synchronize access to the free list, in exactly the same way that they have to synchronize access to any other global data structure. For example, in a native code Delphi, when IsMultiThread is True because you set it manually or you created a TThread , the memory management functions use a critical section to assure exclusive access to the free list. Using a critical...
SOAP Bubbles
Finally, you can force an XmlSerializer to generate SOAP-formatted XML by using an XmlTypeMapping. You create an XmlTypeMapping by creating a SoapReflectionlmporter and passing the root Type to the importer's ImportTypeMapping method. You then pass the type mapping to the XmlSerializer instead of the root Type. That is, instead of serializing like using Stream Write new FileStream Filename, FileMode.Create XmlSerializer Serializer new XmlSerializer typeof Data Serializer.Serialize Write, One...
Nullable Types
Arithmetic and logical operations with a none of the above value C 2.0 adds nullable types. A nullable type is a normal value type with a question mark after it. Where a normal bool enum value can be true or false, a bool nullable bool can be true, false, or null. Similarly, an int can hold any int value or null, while a Color can hold Color.Red, Color.Green, Color. Blue, or null. This adds a not-set value to every number, enum, and struct. Note The point of a nullable type is that it adds null...
Events
The .NET event model is based on delegates Once again, all delegates are compiler-generated classes that descend from MulticastDelegate, which descends from Delegate, which descends straight from object. So, delegates are either assigned i.e., a Delegate instance or unassigned null or Nil . Unassigned delegates are 0-length delegates you will never see an assigned delegate with zero handlers when you use the system Delegate methods to manipulate the invocation list. All assigned delegates...
Folding Regions
Visual Studio and, to a lesser extent, BDS does a pretty good job of generating folding regions automatically you can automatically fold methods, classes, blocks, and so on. When you want to combine several methods and fields into a folding region of their own or when you want to divide a long method into multiple folding regions you use the region and endregion directives. Any text between a region directive and the end of the line will appear in gray, in a gray box, when the region is folded....
Collections
The Array class provides a great deal of standard functionality. Arrays are fixed length and strongly typed, but list classes with a Capacity and a Length can support appending, inserting, and deleting. An ArrayList is a list of object references, and so can hold any data types a List lt T gt is a strongly typed list that can only hold T types. Both these lists are indexed by integers the Hashtable andDictionary lt K, V gt can be indexed by any data type. IEnumerable is everywhere in .NETcode...
Regex Match Methods
From binary tests to getting every match There are three different matching methods IsMatch, Match, and Matches. If all you really care about is whether the regex matched or not, the IsMatch method is a convenient shorthand for calling the Match method and examining the Match object it returns. That is, code like ThisRegex.IsMatch ThisText is a bit smaller and easier to read than ThisRegex.Match ThisText . Success. Since all you care about is Success and not all the details of the Match,...
Threads and Synchronization
It's easy to write multithreaded code what's hard is to write reliable multithreaded code. Threading primitives are not hard to understand, and the .NET implementations are particularly good, but it's all too easy to write code that fails randomly and so is hard to debug. The Thread class executes a delegate in a new thread, and the ThreadPool can execute delegates without creating a new thread every time. The Monitor class provides efficient locking and simple signaling, and there are object...
Polling for Completion
It's not always a good idea to block the application's main thread. It's OK in a command-line utility that simply runs to completion with no user intervention, and it's OK in a web server where each incoming request runs in its own thread, but it's generally not OK in a GUI app, where blocking the main thread means that the app is not responding to mouse clicks and key presses. If you initiate a lengthy asynchronous call from the main GUI thread, you might poll the IAsyncResult.IsCompleted...
Subranges
Represented as an enum, which loses some semantics When you declare a subrange like type Subrange 1 10, the Delphi compiler both chooses an integer type that can hold a Subrange value and creates compile-time constants for High Subrange and Low Subrange . This means you can declare variables of the Subrange type, like var Index Subrange, and can write code that knows the variable's range, like for Index Low Index to High Index . It also means that the compiler can detect illegal assignments...
Lists
A familiar design, with some new features Arrays are great, if they never need to change size, or if they only change size very rarely. However, when you need to add items to a collection one by one, and won't know how big your collection is until you're done, continuously resizing an array is an expensive operation. Typically, you would use an array with an auxiliary Count variable the array length is the current Capacity, while the Count is the number of array elements that actually hold real...
Disposing and Not Finalizing
Many classes dispose, few classes finalize You don't need a finalizer just because you use classes that have finalizers. Those classes are already fail-safe, and your class's finalizer couldn't call any methods on those objects, anyhow. However, if you Dispose of or Close those objects in your Dispose method, they won't need to be finalized. That is, many classes support IDisposable without also supporting finalizers.9 In general, if you use a class that implements IDisposable, you should call...
Unsafe Code 1
As a safety measure, C makes you double-declare unsafe code. That is, you can only declare pointer variables or use pointer operators in unsafe code blocks, and only assemblies compiled with the unsafe switch can have unsafe code blocks. The unsafe switch merely allows you to have unsafe code it doesn't in itself make code unsafe. That is, even when you throw the unsafe switch either through an IDE dialog, or through the eponymous unsafe command-line compiler switch , a normal class like class...
Interfaces 1
Probably the most common interface-related Reflection task is enumerating the public types in a dynamically loaded assembly see the Assemblies section, later in this chapter to find types that support a particular interface. If you are only looking for a single interface, perhaps an IPlugin that your application uses to control its plug-ins, the most obvious way to check whether a type supports an interface is probably to pass Type.GetInterface the interface name a null result means the...
Large Object Heap
It's expensive to relocate large objects The same studies of program behavior that laid the empirical basis for the garbage collector's three-generation design also found that large allocations tend to be long-lived objects IO buffers, application-level caches, and the like. This means that a large object is more likely than a smaller object to need to be relocated. At the same time, relocating a large object is a comparatively expensive operation, both because it runs at memory speed, not CPU...
CLS Rules
While CLS compliance is prima facie a sort of lowest common denominator affair, it's not as bad as it may sound. CLS-compliant code can use inheritance, interfaces, exceptions, and attributes. In fact, it's even OK for a CLS-compliant assembly to include noncompliant features it just has to explicitly label them as noncompliant with the CLSCompliant false attribute. Naturally, if you do expose noncompliant features, like sets or unsigned integers, you should also expose compliant methods that...
Open Types
In 2.0, you can get the typeof of an open type or a closed constructed type just as you can get the typeof a normal closed type such as you can create in 1.x , and the Type class has some new properties and methods to handle open types. The Type. IsGenericType property tells you if a given Type is either an open type or a closed constructed type for example, IsGenericType is false for typeof int but true for both typeof List lt gt and typeof List lt int gt . The related...
Delphi Note Just to be clear Delphi for NET does have metaclasses just as
Metaclasses are Delphi's class of types. Metaclasses support virtual class methods, but metaclasses are most commonly used for polymorphic object creation. For example, you may have used code like function AnyException Meta MetaException const Msg string Exception begin to write a routine that could log and throw any exception. Other common uses of metaclasses include object streaming and container forms. Delphi's form loading depends on metaclasses, and many applications include custom object...
Modifiers
The syntax category that includes access modifiers I've covered the access modifiers like public and private and so on, but their optional position before a member's type is actually just a special case of the more general group of modifiers. There are other modifiers, like static and virtual, new and override. Modifiers come between any attributes and the member's type Member private static int Field 0 There are rules that govern when a modifier is present, so I will discuss each modifier as...
Search
Find elements that match a target, and elements that satisfy a custom predicate In 1.1, there are only two methods that search an array IndexOf and LastIndexOf. IndexOf searches forward, while LastIndexOf searches backward both search an array for a target object, returning an array index or a failure code. In 2.0, the index-of methods gain typed overloads, plus there is a suite of new methods that apply a predicate to an array in various ways. Both IndexOf and LastIndexOf are static methods...
Compiletime Attributes
Attributes that affect compiler behavior Most attributes are essentially transparent at compile time. They are custom metadata, meant to be read at run time. All that the compiler does with these run-time attributes is syntax check the declarations, and add them to the metadata run-time attributes don't affect the compiler's symbol table the way that types and type members do. There are, however, five special attributes that do have compile-time effects CLSCompliant, DllImport, AttributeUsage,...
Note Delphi only needs virtual constructors because it has strongly typed
.NET does not have metaclasses. That does not mean that you cannot do polymorphic object creation. The Chapter2 Polymorphic Delphi project contains the .NET equivalent of the AnyException function function AnyException Meta System.Type const Msg string Exception begin Result Exception Activator.CreateInstance Meta, Msg end WriteLn E is System.ApplicationException The project prints True and then raises an ApplicationException this AnyException function works just as well as its metaclass...
Concatenation Methods
In which we meet some common overload models The String .Concat overloads set a pattern that you'll find repeated throughout this chapter. There are overloads that take one, two, three, or four object parameters, and there is an overload that takes a params object parameter. There are overloads that take two, three, or four string parameters, and there is an overload that takes a params string parameter. All Concat overloads return a single string. Now, as per Chapter 9, the params array...
Wait Handles
More sophisticated locking, at a noticeably higher cost The Monitor class will cover maybe 90 of your synchronization needs. Because using the Monitor class involves neither operating system calls nor finalizers, you should always make the Monitor class your default synchronization solution, only turning to WaitHandle descendants when you need to do cross-process or cross-AppDomain synchronization, or when the Wait Pulse mechanism can't solve your signaling needs. The abstract WaitHandle class...
Iterators 1
Performance is nearly identical to manual enumerators As you've seen, it's not very hard to implement IEnumerable for simple enumerations. Iterators are clearly much simpler for recursive or other complex enumerations, but should you reserve iterators for complex enumerations that aren't easy to implement as two methods and a property One final thing the Chapter12 Shemitz.Collections C project shows is that iterators perform about as well as manual enumerators. The benchmarks vary a bit from...
Delphi Note In Delphi array is a keyword and you have to call static methods as
The static Copy method allows you to copy portions of an array. You can copy either the first N elements from one array to another, or as with the String.Substring method you can copy a given number of elements from a given offset within the source array to a different offset within the target array. Both Copy and CopyTo will raise an exception if the target array is too short, or if the base types are not compatible. While both Copy and CopyTo will copy array elements from one array to...
Colors 1
As per Chapter 15, every pixel that you draw or fill has a 32-bit ARGB color, where A is eight bits of opacity, or Alpha. Except for Color.Transparent, the system colors like Color.Red or Color. LightSeaGreen are all fully opaque. Their alpha channel is 255, or 100 . Similarly, the standard pens and brushes, the Pens.Black and Brushes.LightBlue that I cover later in this chapter are all fully opaque. When you draw an opaque color to a pixel, the pixel's color is set to the color's RGB...
JIT and CIL
.NET is not interpreted. Your code is delivered as CIL Common Intermediate Language , not native machine code. Yet, your code is always compiled to native code before being run. This compilation can happen at install time, but is usually done on a Just In Time basis. Managed code is good for both users and developers, and delivering your code as CIL is key to delivering the benefits of managed code to users intermediate code can be verified before it's run, and running all code through a single...
Wait Callbacks
Reducing the number of blocked threads Many tasks that take significant clock time actually take comparatively little CPU time, because they spend most of their time blocked, waiting for an OS wait handle. They may be waiting for network activity, file IO, a timer, or whatever. As an alternative to creating a thread that spends a lot of time blocked, waiting for one event or another, you can use ThreadPool. RegisterWaitForSingleObject to register an OS wait handle and a WaitOrTimerCallback...
Path Gradient Brushes
A path gradient runs from the outside of an arbitrary graphics path to an arbitrary center point. This can be useful, especially with simple, smooth curves. For example, when you use FillPie to fill a quarter circle with a path gradient centered on the circle's center, you get a rounded border gradient, as in Figure 16-6 and the Chapter16 CornerGradient C project. Similarly, when you use FillEllipse to fill a circle with a path gradient that's somewhat displaced from the circle's center, you...
XML Reader
Using the XmlReader class is a bit more complicated than using the XmlWriter class, especially in 1.x. Using the XmlWriter is a matter of writing a start element writing any attributes or child elements and then writing an end element. The XmlWriter class takes care of details like indenting, and it keeps track of whether the current element has any child elements or not, so that when you write an end element the XmlWriter knows whether it should just write gt to close an empty element, or...
Other Collection Interfaces
Who offers what, and where it matters There are five collection interfaces worth paying attention to IEnumerable, ICollection, IList, IDictionary, and in 2.0 IEnumerable lt T gt . There are also the open interfaces ICollection lt T gt , IList lt T gt , and IDictionary lt K, V gt , but these are not used quite as heavily as their closed counterparts. This section has covered IEnumerable and IEnumerable lt T gt fairly thoroughly. The two are ubiquitous in FCL code you will always use enumerators,...
Sort
The Sort method is heavily overloaded. All but one of the Sort methods fall into one of two groups the IComparable overloads sort types that know how to compare themselves, in ascending order, and the IComparer overloads take a sorting predicate in the form of an instance of an object that implements the IComparer interface. These two basic models are then multiplied by Subarray overloads that sort only a portion of an array by key item sorting that sorts two arrays based on the values in just...
Tip A lazy create property is a good place to use a weak reference
When you need the data again, you can examine the weak reference's Target and or IsAlive properties. The Target property will either contain a valid reference or Nil null the IsAlive property is true whenever Target is non-Nil. If the Target is Nil, that means the weakly referenced object has been garbage collected and you need to re-create it. If the Target is not Nil, you now have a normal strong reference that you can cast to the appropriate type, and that will keep the data from being...
Fonts and Text
Versatile drawing and immutable fonts While the syntax differs slightly, the FCL Font is much like the Delphi TFont it has a font Name that specifies a typeface, as well as Size, Bold, Italic, Underline, and Strikeout properties. You use a Font to draw a string on a Graphics surface, and you can also use a Font to see how many pixels it would take to draw a string on a Graphics surface. Overall, the biggest surprise is that FCL fonts are immutable all Font properties are readonly. With a Delphi...
Latebound Lists
An ArrayList is like an Array that you can Add to The ArrayList class in the System.Collections namespace is a variable-sized list of object values basically an array with an extra count of the slots actually used. The read-only Count property is the number of items in the list. The Capacity property is the size of the underlying array, the number of items the list can hold before it needs to be resized. The ArrayList class has three constructors the no-parameter constructor gives you a new...
Nested Types 1
Applying the Thing model to nested types, you might expect Type. GetType to return a nested type's TypeInfo object, and Type.GetTypes to return an array of TypeInfo objects. But nested types are a special case types can exist outside of a type in way that fields and properties can not. So, even though a Type is a MemberInfo so that Type.GetMember and Type.GetMembers can return Type instances , the Type class is more important than the other MemberInfo classes, and has a short name in the System...
VCLtoFCL Map
Just as WinForms' ShowDialog is almost identical to Delphi's ShowModal, there are several common VCL features that are almost identical to WinForms features, but which are located in different classes or have different names under WinForms. Table 15-1 contains the most commonly used features, with their WinForms equivalents. I cover the differences between Delphi's TCanvas and .NET's Graphics in the next chapter. Table 15-1. FCL Equivalents for Common VCL Constructs Application.ProcessMessages...




