C Sharp

The fixed Statement

The fixed statement has the following syntax: -

fixed (type * ptr = expression) statement -

As I mentioned, the statement tells the GC not to bother with the specified variable. Note that type is an unmanaged type or void, expression is any expression that results in a type pointer, and statement refers to the block of code for which the pinning of the variable is applicable. A simple example follows.

using System;
class Foo
{
    public int x;
}
class Fixed1App
{
    unsafe static void SetFooValue(int* x)
    {
        Console.WriteLine("Dereferenced pointer to modify foo.x");
        *x = 42;
    }
    unsafe static void Main()
    {
        // Create an instance of the structure.
        Console.WriteLine("Creating the Foo class");
        Foo foo = new Foo();
        Console.WriteLine("foo.x intialized to {0}", foo.x);
        // The fixed statement pins the foo object until
        // the enclosing compound statement ends.
        Console.WriteLine("Setting pointer to foo.x");
        // Assign the address of the foo object to a Foo*.
        fixed(int* f = &foo.x)
        {
            Console.WriteLine("Calling SetFooValue passing " +
                              "pointer to foo.x");
            SetFooValue(f);
        }
        // Show that we did alter the member via its pointer.
        Console.WriteLine("After return from " +
                          "SetFooValue, foo.x = {0}", foo.x);
    }
}

This code instantiates a class called Foo and, within a fixed statement, pins that object while assigning the address of its first member to a variable of type int* (the type required by the method SetFooValue). Note that the fixed statement is used only to enclose the code that will be affected if the GC were to move the Foo object. This is a subtle, yet important, issue for larger and longer running code blocks where you want to minimize the amount of time you have an object pinned. Compiling and executing the code above results in the following output: -

Creating the Foo class
foo.x intialized to 0
Setting pointer to foo.x
Calling SetFooValue passing pointer to foo.x
Dereferenced pointer to modify foo.x
After return from SetFooValue, foo.x = 42
NOTE
One important point about pinned variables is the fact that the C# compiler does not restrict access to a pinned variable to the unsafe scope. For example, you can use a pinned variable as an r-value to an l-value that is defined in a broader scope than the unsafe block. Obviously, this can result in an unsafe value being used outside of the unsafe block. In lieu of the compiler emitting a warning or error in this case, it is the developer's responsibility to take care when using pinned variables as r-values.

COM Interoperability

If you've been wondering how all those COM components that you've written through the years play along with the .NET runtime, this section is for you. I'll show you how Classic COM components-yikes, it does hurt to see COM being called Classic COM-are positioned in the .NET world.

A Brave New World

As you've seen throughout this tutorial, there's no doubt that the .NET environment and C# language combine to form a powerful means of building componentized systems. However, what about the tons of existing reusable COM components that you've built through the last few years-not to mention all those cups of coffee and sleepless nights? Does .NET spell the end for those components? Will they work hand-in-hand with the .NET managed runtime? For those of us who program with COM for a living, and for those who live by the "COM is good" mantra, there is great news. COM is here to stay, and .NET framework-managed applications can leverage existing COM components. As you're about to see, classic COM components interoperate with the .NET runtime through an interoperability layer (COM Interop) that handles all the plumbing for messages passed between the managed runtime and the COM components operating in the unmanaged realm.

by BrainBellupdated
Advertisement: