.NET Interoperability at a Glance 1 – Introduction

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

See more Interoperability examples here.

Contents

Contents of this article:

  • Contents
  • Read also
  • Overview
  • Introduction
  • Summary
  • Where to go next

Read also

More from this series:

Overview

.Net Framework Logo
Image via Wikipedia

In this article and the few following it, we’ll try to take a tour in Interoperability in .NET Framework.

In this lesson, we’ll start by an introduction to the concept of Interoperability. In the next few lessons, we’ll have a look at Interoperability and how it fits into the .NET Framework and other technologies.

Since Interoperability is a very huge topic and cannot be covered in just a few articles, we’ll concentrate on Interoperability in .NET Framework (not any other technologies) and summarize its uses.

Here we go!

Introduction

Let’s get hands on the concept of Interoperability and it’s relation to the .NET Framework.

Concept

Interoperability (reduced to Interop) is the ability of two diverse systems or different systems to communicate (i.e. inter-operate) with each other. When I say ‘two systems’ I assume that the first one is always the .NET Framework, since we are interested in .NET and also the interoperability is a very huge topic and cannot be summarized in just a few articles. The other system might be any other software, component, or service based on any technology other than the .NET Framework. For example, we could interoperate with Win32 API, MFC applications, COM/ActiveX components, and so on.

So we have two different systems, the first is the .NET Framework, while the other is any other technology. Our goal is to communicate with that stranger; that’s the main goal of Interoperability in .NET Framework.

Goals and Benefits

Here comes a question (or a few questions!), why do I need interoperation? Why I do need to communicate with other systems at all? If I need specific features, couldn’t I just use existing functionalities of .NET Framework to accomplish my tasks? I can even redevelop them!

We can summarize the answer of those questions in a few points:

  • First, in many cases, you can’t redevelop those components because the functionalities they offer is either very difficult (sometimes impossible) or maybe you don’t sufficient knowledge to redevelop them! Unless if you are very brilliant and have enough knowledge of the Assembly language, you can develop your API that would replace current system API, and then you’ll have also to interoperate with your API to be able to call it from your .NET Framework application.
  • If you’re not convinced yet, this is should be for you. You might be not having enough time to redevelop the component that may take a very long time and effort to complete. Imagine how much time would take to code, debug, and test your component. Plus, you can rely on existing components and trust them, many bugs can appear in your code from time to time and you’ll have to fix them all!
  • Other 3rd party component might not exist, or maybe the company you work for require you to use such those components.
  • You don’t need to reinvent the wheel, do you?

So, including Interop code in your .NET projects is sometimes inevitable (especially when working with Windows API) that you definitely can’t keep yourself away from them.

Summary

So you have now basic understanding of what Interoperability means. As a reminder, Interoperability is the process of two diverse systems communicate with each other. For us, the first system is the .NET Framework. The other system is any other technology (Windows API, MFC, COM/ActiveX, etc.)

You can’t live without Interop, actually you did some interoperation in your work (you may be actually do that every day.)

Now you are ready to take a look at how Interop fits in .NET Framework.

Where to go next

Read more about Interoperability here.

More from this series:

Understanding Value Types and Reference Types

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

Contents

Contents of this article:

  • Contents
  • Introduction
  • Passing Mechanism
  • The Two Genres
  • Value Types
  • Reference Types
  • Boxing and Unboxing
    • Manual Boxing
    • Manual Unboxing
    • Automatic Boxing
    • Automatic Unboxing
  • Summary

Introduction

Today, we’ll have a brief discussion of value types and reference types in .NET framework and how their behavior change while used or passed to functions. We’ll talk about the passing mechanism, the two genres of .NET types, the scope, and the conversion routines between the two genres.

Passing Mechanism

When you pass an object to a function, this object can be passed either by value or by reference.

To pass an object by value means that a copy of the object is passed to the function not the object itself so changes to the object inside the function won’t affect your original copy.

On the other hand, passing an object by reference means passing that object itself so changes to the object inside that function is reflected on your original copy.

Consider the following example. Although the function changed the value of i, the change didn’t affect the original variable that’s because the variable is passed by value.

// C#

static void Main()
{
    int i = 10;
    int j = i;

    j = 5;

    // you expect '5'
    Console.WriteLine(i);
    // but i is still 10 !!

    // Now you try another way

    Sqr(i);

    // you expect '100'
    Console.WriteLine(i);
    // but i is still 10 !!!
}

static void Sqr(int i)
{
    i *= i;
}
' VB.NET

Sub Main()
    Dim i As Integer = 10
    Dim j As Integer = i

    j = 5

    ' you expect '5'
    Console.WriteLine(i)
    ' but i is still 10 !!!

    ' now you try another way

    Sqr(i)

    ' you expect '100'
    Console.WriteLine(i)
    ' but i is still 10 !!!
End Sub

Sub Sqr(ByVal i As Integer)
    i = i * i
End Sub

Now, let’s try something else. The following example passes i by reference.

// C#

static void Main()
{
    int i = 10;

    Sqr(ref i);

    // you expect '100'
    Console.WriteLine(i);

    // you are right!
}

static void Sqr(ref int i)
{
    i *= i;
}
' VB.NET

Sub Main()
    Dim i As Integer = 10

    Sqr(i)

    ' you expect '100'
    Console.WriteLine(i)

    ' you are right!
End Sub

Sub Sqr(ByRef i As Integer)
    i = i * i
End Sub

Notice how the ref keyword in C# (ByRef in VB.NET) changed the overall behavior. Now, i itself is passed to our function, so the changes made in the function affected the original variable (both are the same.)

The Two Genres

Talking about passing object by value or by reference leads up to talk about the two major genres of types in .NET Framework:

  • Value Types
  • Reference Types

Value Types

Value types are those normally passed by value unless you explicitly specify the ref keyword (or ByVal in VB.NET) to override the default behavior and pass the object by reference.

Value types in .NET are those inherit -directly or indirectly- from System.ValueType including all structures, enumerations, and primitives (integers, floats, etc.)

The previous examples use an integer value that’s absolutely a value-type.

Value types are stored on the first section of the memory, the stack. Thus, they are removed from memory as soon as their scope ends. The scope marks the beginning and the end of object’s life (object is considered alive at the time you declare it.) See the following code the marks scopes inside a class.

// C#

class ClassScope
{
    // Scope 1

    void Method1()
    {
        // Scope 1.1

        {
            // Scope 1.1.1
            {
                // Scope 1.1.1.1
            }

            {
                // Scope 1.1.1.2
            }
        }
    }

    void Method2()
    {
        // Scope 1.2

        if (true)
        {
            // Scope 1.2.1

            while (true)
            {
                // Scope 1.2.1.1
            }
        }
    }
}
' VB.NET

Class ClassScope
    ' Scope 1

    Sub Method1()
        ' Scope 1.1
    End Sub

    Sub Method2()
        ' Scope 1.2

        If True Then
            ' Scope 1.2.1

            Do While True
                ' Scope 1.2.1.1
            Loop
        End If
    End Sub
End Class

Reference Types

Reference types are those normally passed by reference and never can be passed by value. Reference types include all objects other than value types, we mean all other classes inherit from System.Object -directly or indirectly- and don’t inherit from System.ValueType.

Reference types are stored in the other version of the memory, the heap, and you can’t determine when the object is removed from memory since the heap is fully managed by the memory manager of .NET, the GC (Garbage Collector.)

Now, let’s see the difference between value types and reference types in action. The following example instantiates two objects, one is a structure (value type) and the other is a class (reference types.) After that, both objects are passed to two functions, both try to change the contents of the objects. The changes of the function affect the reference type outside, while the other value type object outside the function doesn’t get affected.

// C#

static void Main()
{
    ValStruct valObj = new ValStruct();
    RefClass refObj = new RefClass();

    valObj.x = 4;
    valObj.y = 4;
    refObj.x = 4;
    refObj.y = 4;

    MultipleStruct(valObj);
    MultipleClass(refObj);

    Console.WriteLine("Struct:tx = {0},ty = {1}",
        valObj.x, valObj.y);

    Console.WriteLine("Class:tx = {0},ty = {1}",
        refObj.x, refObj.y);

    // Results
    // Struct:  x = 4,  y = 4
    // Class:   x = 8,  y = 8
}

static void MultipleStruct(ValStruct obj)
{
    obj.x *= 2;
    obj.y *= 2;
}

static void MultipleClass(RefClass obj)
{
    obj.x *= 2;
    obj.y *= 2;
}

struct ValStruct
{
    public int x;
    public int y;
}

class RefClass
{
    public int x;
    public int y;
}
' VB.NET

Sub Main()

    Dim valObj As New ValStruct()
    Dim refObj As New RefClass()

    valObj.x = 4
    valObj.y = 4
    refObj.x = 4
    refObj.y = 4

    MultipleStruct(valObj)
    MultipleClass(refObj)

    Console.WriteLine("Struct:tx = {0},ty = {1}", _
            valObj.x, valObj.y)

    Console.WriteLine("Class:tx = {0},ty = {1}", _
            refObj.x, refObj.y)

    ' Results
    ' Struct:  x = 4,  y = 4
    ' Class:   x = 8,  y = 8
End Sub

Sub MultipleStruct(ByVal obj As ValStruct)
    obj.x *= 2
    obj.y *= 2
End Sub

Sub MultipleClass(ByVal obj As RefClass)
    obj.x *= 2
    obj.y *= 2
End Sub

Structure ValStruct
    Public x As Integer
    Public y As Integer
End Structure

Class RefClass
    Public x As Integer
    Public y As Integer
End Class

A little yet very important note: When comparing objects with the double equal signs (or the single sign in VB.NET,) objects are being compared internally using the System.Object.Equals() function. This function returns True if both value objects have the same value or both reference objects refer to the same object (doesn’t matter if both have the same value and are different objects.) Conversely, using the not equals operator (!= in C# and <> in VB.NET) uses the same comparison function, however, it reverses its return value (True becomes False and vice versa.)

Boxing and Unboxing

Boxing is the process of converting a value type into reference type. Unboxing on the other hand is the process of converting that boxed value type to its original state. Boxing and unboxing can be done manually (by you) or automatically (by the runtime.) Let’s see this in action.

Manual Boxing

Consider the following code:

    // C#
    byte num = 25;
    object numObj = num;
    ' VB.NET
    Dim num As Byte = 25
    Dim numObj As Object = num

The last code simply converted a value type (the byte variable) into reference type by encapsulating it into a System.Object variable. Does that really involve that passing the System.Object would be done by reference? Absolutely! (Check it yourself!)

Manual Unboxing

Now you have a boxed byte, how can you retrieve it later, i.e., restore it back to be a value type? Consider the following code:

    // C#
    // Boxing
    byte num = 25;
    object numObj = num;
    // Unboxing
    byte anotherNum = (byte)numObj;
    'VB.NET
    'Boxing
    Dim num As Byte = 25
    Dim numObj As Object = num
    'Unboxing
    Dim anotherNum As Byte = CByte(numObj)

Beware not to try to convert a boxed value to another type not its original type.

Automatic Boxing

Boxing can be done automatically by the runtime if you tried to pass that value type to a function that accepts a System.Object not that value type.

// C#
static void Main()
{
    byte num = 25;

    // Automatic Boxing
    Foo (num);
}

static void Foo(object obj)
{
    Console.WriteLine(obj.GetType());
    Console.WriteLine(obj.ToString());
}
' VB.NET
Sub Main()
    Dim num As Byte = 25

    'Automatic Boxing
    Foo(num)
End Sub

Sub Foo(ByVal obj As Object)
    Console.WriteLine(obj.GetType)
    Console.WriteLine(obj.ToString)
End Sub

Automatic Unboxing

The runtime can automatically unbox a boxed value:

// C#
static void Main()
{
    // Automatic Boxing
    object num = 25;

    // Automatic Unboxing – not really works
    Foo(num);
}

static void Foo(byte obj)
{
    Console.WriteLine(obj.GetType());
    Console.WriteLine(obj.ToString());
}
' VB.NET
Sub Main()
    ' Automatic Boxing
    Dim num As Object = 25

    ' Automatic Unboxing - works
    Foo(num)
End Sub

Sub Foo(ByVal obj As Byte)
    Console.WriteLine(obj.GetType)
    Console.WriteLine(obj.ToString)
End Sub

The difference between C# and VB.NET in the last situation is that VB.NET allows automatic unboxing while C# doesn’t. (Theoretically, VB.NET allows automatic conversion between the vast majority of types, while C# lacks this feature.)

Summary

That was a brief discussion of value types and reference types in .NET Framework. Value types are those normally when passed to a function or copied, a copy of the value is used not the original value. Therefore, changes made to that copy don’t affect the original object.

On the other hand, reference types are those when passed to a function or copied, the object itself is used. Therefore, any changes made inside the function or to the copy do affect the original object (both are the same.)

Value types in .NET are all types inherit from System.ValueType including structures, enumerations, and primitives. All other classes don’t inherit from System.ValueType are reference types.

Boxing is the process of converting a value type to reference type. Unboxing is retrieving that boxed reference type back. To box a variable simple convert it to System.Object. To unbox it, convert it back to its original type. Boxing could also occur automatically when you pass a value type to a function that accepts System.Object not the type itself.

Setting Device Information in MCI

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

Interested in MCI multimedia processing? First check this article out if you didn’t:

Creating a Sound Recorder in C and C#

After we received your feedbacks and comments about th.e article, we decided to add a small appendix to the end of the article about setting information (volume, channel, sampling rate, etc.) to a MCI device (a Waveform device of course.)

Like anything else in MCI, you can set device information using a MCI command (string/numeric), and this time it’s the MCI_SET command.

This command is used to set information about a specific device. This command requires an input parameter of the MCI_SET_PARMS structure. However, that input parameter might have extended members for specific devices. Because we are concentrating of Waveform devices, so we are going to use the MCI_WAVE_SET_PARMS structure that contains the extended members for our device and is defined as following:

typedef struct {
    DWORD_PTR dwCallback;
    DWORD     dwTimeFormat;
    DWORD     dwAudio;
    UINT      wInput;
    UINT      wOutput;
    WORD      wFormatTag;
    WORD      wReserved2;
    WORD      nChannels;
    WORD      wReserved3;
    DWORD     nSamplesPerSec;
    DWORD     nAvgBytesPerSec;
    WORD      nBlockAlign;
    WORD      wReserved4;
    WORD      wBitsPerSample;
    WORD      wReserved5;
} MCI_WAVE_SET_PARMS;

This structure contains all and every little piece of information that can be set to a device. I expect that you read the main article and you are already familiar with members like dwCallback (other members are self-explanatory) that we have talked about many times, and you are fine too with function calls and setting up input parameters, so I won’t get into the discussion of the structure or how you are going to use that command. However, if you need more help setting up the input parameters for the structure, you should take a brief look at the MCI_WAVE_SET_PARMS Structure documentation in the MSDN.

As you know, the MCI_WAVE_SET_PARMS unmanaged structure can be marshaled in C# as following:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MCI_WAVE_SET_PARMS
{
    public IntPtr dwCallback;
    public uint     dwTimeFormat;
    public uint     dwAudio;
    public uint      wInput;
    public uint      wOutput;
    public ushort      wFormatTag;
    public ushort      wReserved2;
    public ushort      nChannels;
    public ushort      wReserved3;
    public uint     nSamplesPerSec;
    public uint     nAvgBytesPerSec;
    public ushort      nBlockAlign;
    public ushort      wReserved4;
    public ushort      wBitsPerSample;
    public ushort      wReserved5;
}

Congratulations! You did set the device information! So how to get them back?

This can be done through the MCI_STATUS (discussed earlier) by setting up the MCI_STATUS_ITEM flag and setting the query item to the required information you need to query about (like MCI_DGV_STATUS_VOLUME to query about volume.)

More about the MCI_STATUS command can be found in the MSDN documentation.

Why you receive a System.Security.SecurityException exception!

Have you ever received an exception like this:

System.Security.SecurityException: xxx.

This exception is thrown whenever you try to access a protected resource while your code doesn’t have the required permissions.

.NET Framework helps protecting computer system from malicious code and software by using a nice feature of CLR called Code Access Security (simply, CAS.) This feature manages the permissions gained by .NET applications, allows code from known vendors and code running from secure locations to run seemlessly without interruption of the CLR, while holds other applications from unknown vendors and applications running from insecure locations (like network shares) to run with restrictions and limitation of access to shared system resources.

A great job from the author is done in the following article:

Understanding .NET Code Access Security

Manually performing a garbage collection!

I was asked whether it’s efficient to perform a manual garbage collection using GC.Collect() or not!

Actually, it’s better to just let the CLR handle it. However, there’re few circumstances where manually performing garbage collection is preferred, such as if some non-recurring event has just happened and this event is highly likely to have caused a lot of old objects to die.

More details are available in Rico Mariani’s…

Have a nice weekend!

Serialization vs. Marshaling

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

Overview

Are you somewhat confused between Serialization and Marshaling? This writing would break this confusion up, it would give you a basic understanding of the process of Serialization and the process of Marshaling, and how you can get the most out of each.

Serialization

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file, a memory buffer, or transmitted across a network connection to be “resurrected” later in the same or another computer environment. And this sequence of bits can be of any format the user chooses; however, they are usually formed as XML or binary.

Serialization comes in many forms in .NET Framework, it can be observed in ADO.NET, Web services, WCF services, Remoting, and others.

For example, calling the WriteXml() function of a DataSet serializes this DataSet into a XML file.

    ds.WriteXml("data.xml");

And if we have such this structure:

    public struct User
    {
        public int id;
        public string name;
    }

we can get the following results if we serialize a collection of that structure into XML:



    
        12
        Mark
    
    
        13
        Charles
    
    
        14
        John
    

Serialization can be observed in Web and WCF services too. The request and parameter information for a function are serialized into XML, and when the function returns the response and the returned data too are serialized into XML. Actually, you don’t have to think about these XML data, CLR handles this for you.

In the same vein, when it comes to Remoting, the sender and recipient must agree to the same form of XML data. That’s, when you send some data CLR serializes this data for you before it sends it to the target process. When the target process receives this XML data, it turns it back (deserializes it) to its original form to be able to handle it.

Thus, the process of converting data structures and objects into series of bits is called Serialization. The reverse of this process, converting these bits back to the original data structures and objects, is called Deserialization.

Therefore, the following ADO.NET line does deserializes the XML file:

    DataSet ds;
    ds.ReadXml("data.xml");

And when your application receives response from the server or from another process, the CLR deserializes that XML data for you.

So why XML is preferred over binary serialization? That’s because XML is text-based. Thus, it’s free to be transmitted from a process to another or via a network connection, and firewalls always allow it.

Marshaling

Marshaling is the process of converting managed data types to unmanaged data types. There’re big differences between the managed and unmanaged environments. One of those differences is that data types of one environment is not available (and not acceptable) in the other.

For example, you can’t call a function like SetWindowText() -that sets the text of a given window- with a System.String because this function accepts LPCTSTR and not System.String. In addition, you can’t interpret (handle) the return type, BOOl, of the same function, that’s because your managed environment (or C# because of the context of this writing) doesn’t have a BOOL, however, it has a System.Boolean.

To be able to interact with the other environment, you will need to not to change the type format, but to change its name.

For example, a System.String is a series of characters, and a LPCTSTR is a series of characters too! Why not just changing the name of the data type and pass it to the other environment?

Consider the following situation. You have a System.String that contains the value €œHello€:

System.String str = "Hello";

The same data can be represented in an array of System.Char too, like the following line:

System.Char[] ch = str.ToCharArray();

So, what is the difference between that System.String variable and that System.Char array? Nothing. Both contain the same data, and that data is laid-out the same way in both variables. That’s what Marshaling means.

So what is the difference between Serialization and Marshaling?

C# has a System.Int32, and Windows API has an INT, and both refer to a 32-bit signed integer (on 32-bit machines.) When you marshal the System.Int32 to INT, you just change its type name, you don’t change its contents, or lay it in another way (usually.) When you serialize a System.Int32, you convert it to another form (XML for instance,) so it’s completely changed.

Summary

Look, after I get back to Wikipedia documentation for Marshaling, I realized that my answer was so specific to C#!

I mean that, Marshaling is a very general term used to describe transformations of memory. Theoretically, it’s more general than Serialization. In Python for instance, the terms Marshaling and Serialization are used interchangeably. There (in Python,) Marshaling = Serialization, and Serialization = Marshaling, there’s no difference. In computer methodology, there’s a silent difference between Marshaling and Serialization (check the Wikipedia definition.)

So what is that System.MarshalByRefObject class? Why that name -specifically- was used? First, System.MarshalByRefObject class allows objects to be passed by reference rather than by value in applications that use Remoting.

Personally, I like to say that Microsoft .NET Framework team’s name was very scientific when they have called that object “MarshalByRefObject” with respect to that silent difference between serialization and marshaling or maybe that name was derived from Python, dunno!

After all, we should keep in mind that in .NET methodology, there’s a big difference between Serialization and Marshaling, Marshaling usually refers to the Interop Marshaling. In .NET Remoting, it refers to that serialization process.

By the way, Marshalling is so named because it was first studied in 1962 by Edward Waite Marshall, then with the General Electric corporation.

That’s all.

Have a nice day!

Microsoft Agent; Providing a Custom Popup Menu

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

A second honeymoon with Microsoft Agent. Do you remember our article Programming Microsoft Agent in WinForms and our sample application PartIt? After you have included your desired agent in your application, are you feeling bad with the default popup menu? If so, then you are in the right place (welcome :).)

Enough talking, let’s get to work! First, prepare your code that loads the Microsoft Agent and brings it to the screen.

After that, create your System.Windows.Forms.ContextMenuStrip and add your required items (well, including ‘Hide’ maybe) and finish the item event handlers.

Now, let’s complete it. Get to the code that loads the agent character (e.g. calls the Characters.Load() method of the agent control object, AxAgentObjects.AxAgent) and just disable the AutoPopupMenu flag/property of the character object, AgentObjects.IAgentCtlCharacterEx. This flag/property determines whether to allow the default popup menu or not.

For example, the following code disables this property:

    AxAgentObjects.AxAgent agentCtl;
    AgentObjects.IAgentCtlCharacterEx agentChar;

    // initializing 'agentCtl'
    // . . .

    agentCtl.Characters.Load("Merlin", "merlin.acs");
    agentChar = agentCtl.Characters.Character("Merlin");
    agentChar.AutoPopupMenu = false;

Next comes the interesting point. When the character is clicked, the ClickEvent event of the agent control (AxAgent) fires. So the next step is to handle this event and to provide your code that brings up your custom context menu. Consider the following code:

// agentCtl.ClickEvent += agent_ClickEvent;

public void agentCtl_ClickEvent(object sender, AxAgentObjects._AgentEvents_ClickEvent e)
{
    if (e.characterID == "Merlin")  // check for this if you have many characters
    {
        if (e.button == 2) // 1 = left, 2 = right
        {
            myContextMenu.Show(e.x, e.y);
        }
    }
}

Well done!

Have a nice Sunday!

9 Rules about Constructors, Destructors, and Finalizers

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

Overview

First, this writing concentrates of and compares between three programming languages, C#, C++/CLI, and ISO/ANSI C++. It discusses 9 rules that every developer should keep in mind while working with constructors, destructors, and finalizers and class hierarchies:

  • Rule #1: Contrsuctors are called in descending order
  • Rule #2: In C# lexicology, a destructor and a finalizer refer to the same thing
  • Rule #3: Destructors are called in ascending order
  • Rule #4: Finalizers are a feature of GC-managed objects only
  • Rule #5: You cannot determine when finalizers would be called
  • Rule #6: C++/CLI differs between destructors and finalizers
  • Rule #7: In C++/CLI and classic C++, you can determine when destructors are called
  • Rule #8: In C++/CLI, destructors and finalizers are not called together
  • Rule #9: Beware of virtual functions in constructors

Rule #1: Constructors are called in descending order

Rule #1: Constructors are called in descending order; starting from the root class and stepping down through the tree to reach the last leaf object that you need to instantiate. Applies to C#, C++/CLI, and ANSI C++.

Let’s consider a simple class hierarchy like this:

    class BaseClass
    {
        public BaseClass()
        {
            Console.WriteLine("ctor of BaseClass");
        }
    }

    class DerivedClass : BaseClass
    {
        public DerivedClass()
        {
            Console.WriteLine("ctor of DerivedClass");
        }
    }

    class ChildClass : DerivedClass
    {
        public ChildClass()
        {
            Console.WriteLine("ctor of ChildClass");
        }
    }

ChildClass inherits from DerivedClass, and DerivedClass, in turn, inherits from BaseClass.

When we create a new instance of ChildClass using a simple line like this:

    static void Main()
    {
        ChildClass cls = new ChildClass();
    }

the code outputs the following results:

ctor of BaseClass
ctor of DerivedClass
ctor of ChildClass

Rule #2: In C# lexicology, a destructor and a finalizer refer to the same thing

Rule #2: In C# lexicology, a destructor and a finalizer refer to the same thing; the function called before the object is fully-removed from the memory (i.e. GC-collected). Applies to C# only.

Let’s consider the same class hierarchy but with destructors:

    class BaseClass
    {
        public ~BaseClass()
        {
            Console.WriteLine("dtor of BaseClass");
        }
    }

    class DerivedClass : BaseClass
    {
        public ~DerivedClass()
        {
            Console.WriteLine("dtor of DerivedClass");
        }
    }

    class ChildClass : DerivedClass
    {
        public ~ChildClass()
        {
            Console.WriteLine("dtor of ChildClass");
        }
    }

When you define a class destructor with that C++-alike syntax (preceding the function name with a ~) the compiler actually replaces your destructor with an override of the virtual Object.Finalize() function. That is, before the object is removed (i.e. GC-collected) from the memory, the finalizer (i.e. destructor) is called first. This finalizer first executes your code. After that it calls the finalizer of the base type of your object. If we could decompile our assembly, we would see that our destructor in the ChildClass (so other classes) has been replaced with this function:

        protected virtual void Finalize()
        {
            try
            {
                Console.WriteLine("dtor of ChildClass");
            }
            finally
            {
                base.Finalize();
            }
        }

Rule #3: Destructors are called in ascending order

Rule #3: Destructors are called in ascending order, starting from the leaf object that you need to instantiate and moving up through the tree to reach the very first base class of your object. In reverse of constructors calling order. Applies to C#, C++/CLI, and ANSI C++.

Now, instantiate your class:

    static void Main()
    {
        ChildClass cls = new ChildClass();

        // 'cls' is removed from memory here
    }

the code should outputs the following results:

dtor of ChildClass
dtor of DerivedClass
dtor of BaseClass

Rule #4: Finalizers are a feature of GC-managed objects

Rule #4: Finalizers are a feature of GC managed objects (i.e. managed classes). That’s because the finalizer is called only when the GC removes the object from the memory (i.e. frees memory associated with).

Now, try to create a simple structure with a destructor:

    struct MyStruct
    {
        ~MyStruct()
        {
            Console.WriteLine("dtor of MyStruct");
        }
    }

The code won’t compile. That’s because that GC doesn’t handle structures.

Rule #5: You can’t determine when finalizers would be called

That’s because you don’t know when the next garbage collection would occur, even if you performed a manual garbage collection (using System.GC.Collect() function) you won’t know exactly when memory would be released. In addition, GC always delay releasing of finalizable object, it puts them in a special GC queue called freachable (pronounced ef-reachable, F stands for Finalize) queue. Applies to C# and C++/CLI (.NET.)

Rule #6: C++/CLI differs between destructors and finalizers

Rule #6: C++/CLI differs between destructors and finalizers. That is, finalizers are called by GC, and destructors are called when you manually delete the object.

Let’s consider the same example but in C++/CLI:

ref class BaseClass
{
public:
	BaseClass()
	{
		Console::WriteLine("ctor of BaseClass");
	}

	~BaseClass()
	{
		Console::WriteLine("dtor of BaseClass");
		GC::ReRegisterForFinalize(this);
	}
};

ref class DerivedClass : BaseClass
{
public:
	DerivedClass()
	{
		Console::WriteLine("ctor of DerivedClass");
	}

	~DerivedClass()
	{
		Console::WriteLine("dtor of DerivedClass");
		GC::ReRegisterForFinalize(this);
	}
};

ref class ChildClass : DerivedClass
{
public:
	ChildClass()
	{
		Console::WriteLine("ctor of ChildClass");
	}

	~ChildClass()
	{
		Console::WriteLine("dtor of ChildClass");
		GC::ReRegisterForFinalize(this);
	}
};

When we run the code:

int main()
{
	ChildClass^ cls = gcnew ChildClass();
}

it outputs the following results:

ctor of BaseClass
ctor of DerivedClass
ctor of ChildClass

The destructors are not called. Why? Unlike C#, in C++/CLI there is a big difference between destructors and finalizers. As you know, the finalizer is called when the GC removes the object from the memory. Destructors, on the other hand, are called when you destroy the object yourself (e.g. use the delete keyword.)

Now, try to change the test code to the following:

int main()
{
	ChildClass^ cls = gcnew ChildClass();
	delete cls;
}

Run the code. Now, destructors are called.

Next, let’s add finalizers to our objects. The code should be like the following:

ref class BaseClass
{
public:
	BaseClass()
	{
		Console::WriteLine("ctor of BaseClass");
	}

	~BaseClass()
	{
		Console::WriteLine("dtor of BaseClass");
		GC::ReRegisterForFinalize(this);
	}
	!BaseClass()
	{
		Console::WriteLine("finz of BaseClass");
	}
};

ref class DerivedClass : BaseClass
{
public:
	DerivedClass()
	{
		Console::WriteLine("ctor of DerivedClass");
	}

	~DerivedClass()
	{
		Console::WriteLine("dtor of DerivedClass");
		GC::ReRegisterForFinalize(this);
	}
	!DerivedClass()
	{
		Console::WriteLine("finz of DerivedClass");
	}
};

ref class ChildClass : DerivedClass
{
public:
	ChildClass()
	{
		Console::WriteLine("ctor of ChildClass");
	}

	~ChildClass()
	{
		Console::WriteLine("dtor of ChildClass");
		GC::ReRegisterForFinalize(this);
	}
	!ChildClass()
	{
		Console::WriteLine("finz of ChildClass");

	}
};

As you see, the syntax of constructors, destructors, and finalizers are very similar.

Now, let’s try the code:

int main()
{
	ChildClass^ cls = gcnew ChildClass();
}

GC would call finalizers and the code would outputs the following:

ctor of BaseClass
ctor of DerivedClass
ctor of ChildClass
finz of ChildClass
finz of DerivedClass
finz of BaseClass

Rule #7: In C++/CLI and C++, you can determine when destructors are called

Now, try to destroy the object yourself:

int main()
{
	ChildClass^ cls = gcnew ChildClass();
	delete cls;
}

The delete statement calls object destructors and removes the object from memory.

Or else, declare the object with stack-semantics:

int main()
{
	ChildClass cls;
}

Now, destructors are called when the scope of the object ends.

Rule #8: In C++/CLI, destructors and finalizers are not called together

Rule #8: In C++/CLI, destructors and finalizers are not called together. Only destructors or finalizers are called. If you manually delete the object or you declare it with stack-semantics, destructors are called. If you leaved the object for GC to handle, finalizers are called.

Now try to run the code. The code should outputs the following results:

ctor of BaseClass
ctor of DerivedClass
ctor of ChildClass
dtor of ChildClass
dtor of DerivedClass
dtor of BaseClass

Rule #9: Beware of virtual functions in constructors

Rule #9: Beware of virtual (overridable) functions in constructors. In .NET (C# and C++/CLI,) the overload of the most derived object (the object to be instantiated) is called. In traditional C++ (ISO/ANSI C++,) the overload of the current object constructed is called.

Let’s update our C# example:

class BaseClass
{
    public BaseClass()
    {
        Foo();
    }

    public virtual void Foo()
    {
        Console.WriteLine("Foo() of BaseClass");
    }
}

class DerivedClass : BaseClass
{
    public DerivedClass()
    {
    }

    public override void Foo()
    {
        Console.WriteLine("Foo() of DerivedClass");
    }
}

class ChildClass : DerivedClass
{
    public ChildClass()
    {
    }

    public override void Foo()
    {
        Console.WriteLine("Foo() of ChildClass");
    }
}

When you execute the code:

    static void Main()
    {
        ChildClass cls = new ChildClass();
    }

you would get the following results:

Foo() of ChildClass

The same code in C++/CLI:

ref class BaseClass
{
public:
	BaseClass()
	{
		Foo();
	}

	virtual void Foo()
	{
		Console::WriteLine("Foo() of BaseClass");
	}
};

ref class DerivedClass : BaseClass
{
public:
	DerivedClass()
	{
	}

	virtual void Foo() override
	{
		Console::WriteLine("Foo() of DerivedClass");
	}
};

ref class ChildClass : DerivedClass
{
public:
	ChildClass()
	{
	}

	virtual void Foo() override
	{
		Console::WriteLine("Foo() of ChildClass");
	}
};

The code outputs the same results.

But what if you need to call the virtual function of the BaseClass? Just change the code to the following:

ref class BaseClass
{
public:
	BaseClass()
	{
		BaseClass::Foo();
	}

	virtual void Foo()
	{
		Console::WriteLine("Foo() of BaseClass");
	}
};

Now, the code outputs:

Foo() of BaseClass

Let’s consider the same example but in classic ISO/ANSI C++:

class CBaseClass
{
public:
	CBaseClass()
	{
		Foo();
	}
	virtual void Foo()
	{
		cout << "Foo() of CBaseClass" << endl;
	}
};

class CDerivedClass : CBaseClass
{
public:
	CDerivedClass()
	{
	}

	virtual void Foo() override
	{
		cout << "Foo() of CDerivedClass" << endl;
	}
};

class CChildClass : CDerivedClass
{
public:
	CChildClass()
	{
	}

	virtual void Foo() override
	{
		cout << "Foo() of CChildClass" << endl;
	}
};

Now, run the code. It should outputs:

Foo() of BaseClass

In classic C++, the overload of the function of the class being constructed is called unlike C# and C++/CLI (.NET in general.)

Video: What’s New in C# 2/3/4

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

Here’s the complete “What’s New in C#” webcast series of Bruce Kyle (ISV Architect Evangelist of Microsoft) from Channel 9 blog:

What’s new in C# 2:

We will try to update this list as soon as new items release.

Bad Practices: Locking on Non-shared Objects in Multi-threaded Applications

Actually, I was having a problem synchronizing threads calling a function. If we could regenerate the bug, we would end up with code like this:

static void Main()
{
    Thread[] arr = new Thread[10];

    for (int i = 0; i < 10; i++)
    {
        arr[i] = new Thread(ThreadProc);
        arr[i].IsBackground = true;
        arr[i].Start(new object());
    }

    foreach (Thread t in arr)
        t.Join();
}

private static void ThreadProc(object obj)
{
    lock (obj)
    {
        int i = 0;
        while (i < 10)
        {
            Thread.Sleep(1);
            Console.WriteLine("Thread #{0},t{1}",
                Thread.CurrentThread.ManagedThreadId, i++);
        }
    }
}

And when we execute this code the results would be like this:

Thread #4,      2
Thread #3,      3
Thread #5,      1
Thread #7,      0
Thread #5,      2
Thread #6,      1
Thread #3,      4
Thread #4,      3
Thread #8,      1
Thread #9,      0

What is the problem with this code? It starts multiple threads and passes them a locking object and the object is locked successfully using the lock statement, so why threads overlap? Why the synchronization doesn’t take effect?

Well, after a long period and after pushing a new thread in the MSDN forums (we are all developers do make silly mistakes, aih? :P), I come up with the solution and discovered the drawback of the code.

The problem was that each time we start off a thread we pass it a new locking object different from the others:

        arr[i].Start(new object());

Therefore, every thread is locking on its own objects, so no thread synchronization take effect.

The solution is very easy, you should lock on a shared object; an object that is shared between all your threads accessing this block of code. Read more about thread synchronization here.

For example, we should change our code to the following:

private static object _lockThis = new object();
static void Main()
{
    Thread[] arr = new Thread[10];

    for (int i = 0; i < 10; i++)
    {
        arr[i] = new Thread(ThreadProc);
        arr[i].IsBackground = true;
        arr[i].Start();
    }

    foreach (Thread t in arr)
        t.Join();
}

private static void ThreadProc(object obj)
{
    lock (_lockThis)
    {
        int i = 0;
        while (i < 10)
        {
            Thread.Sleep(1);
            Console.WriteLine("Thread #{0},t{1}",
                Thread.CurrentThread.ManagedThreadId, i++);
        }
    }
}

Finally, this was one of the bad practices and mistakes me (and many others too) fall in. Honestly, I would like to start my Bad Practices series :”>. I would write about problems I came across and solutions I found for them. In addition, I’m thinking of starting the Questions series. I got a huge number of questions every week, if we could publish them I think it would be great for all.

Have a nice day!