Hernan's profile3D StudiosPhotosBlogLists Tools Help

Hernan

Occupation
Location
Photo 1 of 8

Weather

Loading...

MSDN

Loading...Loading...

MSDN SQL

Loading...Loading...

MSDN Magazine

Loading...Loading...

Windows Vista

Loading...Loading...

3D Studios

Digital Ideas
July, 2006

Collections++

Problems of the past

One of the most annoying programming issues with the .NET Framework was Array management. Using a Type[]-kind arrays is complicated, they cannot grow nor shrink, they don't have Add or Remove functions, and so on. From my point of view, arrays were left as a somehow untouched feature of the Framework. To bring a solution, they've introduced the System.Collections Namespace which provided array-like classes like the ArrayList, which has almost everything you could ask for to a native array: Add, Remove, Contains methods among others and it can auto-grow and shrink itself on demand. But this solution introduced yet another problem: ArrayLists are NOT strong-typed. While that can be considered a flexibility, it can also let in programming issues like, mistakenly, insert a string into an array of what you think are integers and get runtime type-casting exceptions thrown. We should also mention some of the performance issues that ArrayLists bring to table, but we'll talk about that later on.

Generics to the rescue

With the introduction of the version 2.0 of the .NET Framework, Microsoft has added Generics support, which is a brand new feature. Generics are not a feature specific to C# or VB, Generics are a feature of the Framework itself and both of the aforementioned languages support them as, I guess, C++ and J# do. Generics have also been added to the ECMA standard so don't be surprised by the fact that the Mono community has already added support to their runtimes and to the C# 2.0 (or GMCS) compiler as well (although they say that that's not yet finished).

Brief introduction

Brief and concise: As well as parameters turn your methods useful, Generics allow you to pass parameters to your Types and turn them yet more useful than they already are.

Case examples

Let's say that you're working on your little business management application and you have two types which represent your Customers and your Representatives respectively:

//We don't care about the implementation
public class Customer {...}
public class Representative {...}

By normal data flow, is obvious that the Representative Class will have a collection of Customers which the Representative represents (seriously, isn't that logic?). In the .NET Framework 1.x, we'd write:

using System.Collections;
.
.
.
public class Representative
{
ArrayList customers;

public Representative() { customers = new ArrayList(); }
}

The first thing that we realize here is that the ArrayList is a collection of objects, not Customers. Therefore, whenever you add a Customer, is has to be casted to an object and when you read one out, it needs to be casted back. So:

//Add

//Either
customers.Add ( new Customer() ); //Implicit Cast
//Or
customers.Add ( (object)( new Customer() ) ); //Explicit Cast

//Read

//Either
Customer customer0 = customers[0]; //Implicit Cast
//Or
Customer customer0 = (Customer)customers[0]; //Explicit Cast

All that takes some processing. The runtime has to check whether the second can be done. Imagine that you have an array of Integers. They need to be Boxed and Unboxed, which also needs processing...

Something like the following could happen, too:

customers.Add ( “I was sleepy when I wrote this. I forgot the coffee.” ); //A string comes in. i.e.: In index 0
Customer customer0 = (Customer)customers[0]; //Oops, this will cause a runtime exception.

Resuming: While ArrayLists are powerful and simple to use, they need some unnecessary processing and are not strong-typed.

Generics' features and improvements

So far we've read the bad news, but we'll now read the good ones, followed by code examples, of course.
Generics allow strong-typed, auto-growing, on-demand shrinking arrays filled with useful methods as well as other “dynamisms” for delegates, for example. So, let's see how a generic List would look like:

public List<T>
{
int count;
T[] objects;

public List() {}

public void Add ( T value ) { objects[++count] = value; }
public T Read ( int index ) { return objects[index]; }
}

The first question you'd ask yourself should be: “What does that T thing mean?!” I'll tell you. Analyze the following class:

public ListOfCustomers
{
int count;
Customer[] customers;

public ListOfCustomers() {}

public void Add ( Customer value ) { customers[++count] = value; }
public Customer Read ( int index ) { return customers[index]; }
}

In the second case, the only object, I'll say that twice the only object that we can add and read to and from the array is “Customer”. So, suppose that you need a list of Representatives, well, you'd need to write the same thing once again and change the data type to Representative (if you want strong-typing). Wouldn't it be easier if we just instantiated the first List twice like follows

List<Customer> customers = new List<Customer> ();
List<Representative> representatives = new List<Representative> ();

and still have the same result? Yes, it'd be and is possible today!

I mentioned improvements and I won't finish the article without explaining why I did. Do you remember what I said about the type-casting and boxing and unboxing that has to be done with ArrayLists? Well, as we're passing this T parameter to the List type and this type is then used to define the type that the array of objects will be, the type passed to our Add method and the return type of our Read method, casting is unnecessary. Boxing and unboxing is unnecessary too if we'd pass in an int or float, for example. So, the type that the list uses is always the one that you pass in the T parameter. Isn't that great?

Filtering Ts out

It may happen that you only want T to be a Class, or a Struct for example. Well, that can be fixed like the following:

public class List<T> where T:class //T must be a Class.
//Or
public class List<T> where T:struct //T must be a Struct.

In the CLR

As I said, Generic types are initialized at runtime which would mean that if we need two lists of different types, the list would have to be recompiled every single time. Well, here's where the CLR's intelligence comes in. If it is the first time in our whole application's run time, the list will be compiled. If it's not the first time, and the type that you're passing in is a Reference Type, the code is shared as in the underlying assembler code, they're just pointers. So, for Reference Types, they're compiled just once. If the type is a Value one, the list will be recompiled every time.

Go and run CSC!

To close, be aware of the following: There's already a type List<T> in the System.Collections.Generics Namespace (where all the generic types are), so don't implement it by yourself. I also mentioned that generics add some “dynamism” to delegates and stuff, but we'll cover that in some future article. Last word: Read List<T> as “List of T”.

Be Generic!

Hernán A. Gatta

May, 2006

SuSE is live baby!

Alright, I’ve been for years trying to get a functional Linux installation. I guess the attraction of unknown technology keeps me trying new stuff. I remember some years ago my try to get Corel Linux 1.0 November 1999 Release up and running on my PII PC: X didn't run (yes, X Windowing System – “System”). I gave up. Fast forward to today, I had to try again. I downloaded SuSE 10.1 from http://en.opensuse.org/. I opted for the DVD which is a 3.49GB download. I got it from a server somewhere in Italy from which I reached ~450KB/s of download rate (compared to the ~68KB/s from their servers). I burnt the ISO Image and I booted the DVD. I installed it following the pre-defined settings and I got it up and running perfectly, even dual-boot with WXP is perfect.

 

I’ll be posting about some of the issues that I had to “tackle” soon.

 

Happy installing!!! J


Hernán A. Gatta

April, 2006

Managed/Unmanaged Interoperability

The .NET Framework is quite a new technology and native code stills around, so isn’t a surprise the fact that the Framework provides interoperability with native libraries. There are three methods that you can use to use native libraries.

COM References:

If you have a COM Component that you’d like to use from your managed application, this is the best way of doing it. Simply do right click over the project from which you’ll be referencing the component and choose “Add Reference...” Then click the “COM” tab. Visual Studio will scan the Windows Registry for registered COM Libraries and will show you what it has found. After you select the components that you’d like to use, click OK. Then you’ll have a namespace corresponding to the components you’ve selected.

Managed Wrapper Classes:

As the name suggests, it implies mapping your native class into a .NET Class. For example, you may have the following:
Native Class:

            MethodSomething() { Implementation }
 

Managed Class:
            MethodSomething() { NativeClass.MethodSomething(); }
 

That is, you expose the all the same methods through your managed class and you call the unmanaged implementation.

P/Invokes:

As I’ve explained in other post, this is the lowest level communication between Managed and Unmanaged. You can use this to make calls into almost anything. Check the previous post for more information.

Something to be aware of when using any of the above: The GC will NOT do memory clean-up of unmanaged components, so it’s up to you to do it.

Happy Interop!


Hernán A. Gatta

April, 2006

A primer to Integer Overflows/Underflows

1 bottle of beer on the wall, 1 bottle of beer, you take 1 down, pass it around, 0 bottles of beer on the wall.
0 bottles of beer on the wall, 0 bottles of beer, you take 1 down, pass it around, 4294967295 bottles of beer on the wall.

Beer companies would be really happy!


Hernán A. Gatta

April, 2006

Controlling Objects' Lifetimes

All .NET objects contain a Finalize() method that is inherited from the ultimate base System.Object class. Finalizers are methods that are used to release any unmanaged resources and perform clean-up operations before the object gets garbage collected. If you need to do such clean-up, you can always override the method with your own implementation. Finalizers are non-deterministic, that is, you can’t tell when they are going to be called as that’s up to the GC; so you shouldn’t put any code in it that you depend on being called. Only implement Finalize() if your class really needs one as objects with finalizers take longer to allocate and longer to destroy because the finalizer has to be called. Now, there’s no way to call an object’s finalizer explicitly so what if you want to release an object’s resources? Putting the code into the finalizer won’t work because you don’t know when it is going to be called and you can’t call it by yourself, so in the .NET Framework we have the IDisposable Interface which provides a simple clean-up model for your classes. Classes that implement this interface must implement a Dispose() method that is used with the same purposes as the finalizers plus you can free managed resources if you wish as well. Calling code can run Dispose() to free up resources and leave the garbage collection on the object up to the system.

Finalize and Dispose: Make them live together.

First, Dispose() releases resource on demand, but the object that has been disposed will still be alive, which means that if some other code tries to access the object after disposal, an ObjectDisposedException will be thrown. Second, if you release your resources with Dispose() and sometime after the object gets garbage collected, the finalizer will be called; which means that you have to set a flag to let the finalizer know that the object has already been disposed and so it won’t try to release the same resources again.

What about Destructors now?

In C# and in C++ you can specify objects Destructors which are basically finalizers with but using the old C++ syntax. If you implement a destructor for your class, the compiler will write a Finalize() method for you by copying the destructor’s code into the finalizer, calling Finalize() for its base class if any and creates a virtual destructor to, first of all, prevent the garbage collector to undertake its own finalizing routines on the object and then calls the finalizer that has been created in the previous step.

Happy allocation!


Hernán A. Gatta

.NET's GC

We’ve got a short title this time. Well, if you’re wondering what the GC is, here’s the answer: The GC is a Garbage Collector that is directly built into the CLR. Its task is to track unused objects and delete them from memory. That means that we don’t have to worry about memory management as we used to do with native code. Thousands of C++ developers around the world have only dreamed about having this feature integrated into their runtime libraries, so guys, you now have C++ .NET that contains a nice-working GC. Of course we optionally still have the control of objects' lifetimes.

Problems with Manual Memory Management:

Manual memory management is one of the biggest causes of bugs in unmanaged applications. Doesn’t matter how intelligent we can be, if it’s up to us to take care of destroying every object we create and at the correct time, bugs will always be there.

One of the common mistakes is not freeing memory up; also called memory leakage. It happened to me many years ago with one of my first VB6 applications. It was a tiny text editor with some rich text formatting capabilities and image importing. The program started up using 40MB of RAM and could end up using 140MB after editing a few documents with large images. If you create an object in native code, it will remain there until your application is shut down. In some extreme cases, an application could leak memory up to the point that it will start interfering with other applications and with the OS itself, and most probably, it will make your computer crash.

The worst memory management mistake is when you free memory up at the wrong time. If delete gets called on an object too soon and another piece of code tries to access that object, you can expect a run-time exception. The same will happen if delete gets called more than once on the same object.

Although manual memory management allows you to do some really tiny adjustments to your code, it can mess it up as well.

The .NET Approach:

As I’ve said before, the Garbage Collector is a new automated-memory management system that tracks objects in memory and watches if the object is going to be used or not in the code that follows. If the second is true, the object will be just deleted from memory. Although that may sound simple, it isn’t. Memory for objects is allocated on the managed heap. Every object on the heap takes some memory and if you keep allocating, at some point you’ll run out of space. For this, the Garbage Collector is invoked to see if there are some unused and unreferenced objects and it takes them away, leaving more free space in the heap for more objects.

Under the covers, every .NET object belongs to a specific generation. When an object is first allocated, it is placed in generation 0 and then they get promoted to higher generations with longer lived objects; that is, you don’t need to run garbage collections on the whole heap, you just have to consider the age of an object.

The collection occurs when generation 0 is full. Unused objects are deleted and objects that didn’t get collected are promoted to generation 1. The GC always runs first on generation 0. If it doesn’t free up enough memory, it will continue on higher generations. On .NET 1.0, only generations 0, 1 and 2 were supported.

If you ever need to access the GC by yourself, you can use the System.GC class. You can run a collection on the default generation or you can specify one by using the Collect method. If you want to know the generation an object belongs to, you can call the GetGeneration method passing in a reference to a specific object.

Happy collection!


Hernán A. Gatta

April, 2006

What the .NET Framework can't do, P/Invokes can

As we all know, creating class libraries that encapsulate every single method of the Windows API is almost impossible, so it wouldn’t be hard to believe that .NET can’t do everything. But what happens when you need to do something that .NET can’t? Well, there are a few answers but everyone ends up in a P/Invoke. That’s the short for Platform Invoke and it’s the lowest level possible communication between Managed and Unmanaged Code. P/Invokes can be done against the Windows API or any other library (they don’t need to be COM Components). Let’s take a look at some Visual Basic .NET (2.0) code and analyse it word by word:

Public Declare Unicode Function SetWindowText Lib "user32.dll" Alias "SetWindowTextW" (ByVal hWnd As Long, ByVal lpString As String) As Long

Public: As when you define a method, is its scope.

Declare: Same as “extern” for other languages. Means that the function is somewhere outside your application.

Auto | Ansi | Unicode: Encoding. For non-NT systems better use ANSI, for NT systems, Unicode and if you’re not sure of where you’re application will run, use Auto.

Function | Sub: Same as when use in a Visual Basic .NET application, if the method returns a value, use Function otherwise, use Sub.

SetWindowText: The name of the method.

Lib: Where the method is located. If the library you’re calling into is a well-known one (such as a Windows API library), you can just type the name of it like in this case otherwise, you’ll need to type the whole path.

user32.dll: In this case, there’s the method located.

Alias: An alias for the method, in this case the last W at the end denotes “Unicode”, that is that the string that we’ll be passing to lpString is Unicode-encoded. The ANSI variant is “A” instead of “W”. Normally, you should accord the encoding at the beginning with the method’s alias.

The rest are the function parameters and the return type. Remember to use native types, never pass a SqlConnection Object to one of those or you’ll run into trouble.


That function is the one with which I’ve learnt P/Invokes on VB6. Old good times those…

Happy coding!


Hernán A. Gatta

February, 2006

Asynchronous Operations on .NET

Have you ever wanted to show a nice progress bar while executing something in the background but you couldn’t because you had no idea on how to pass parameters to a thread? If that did happen to you, you may remember the frustration you first felt. There’s not too much about asynchronous operations, and getting to do them on .NET is quite straightforward. Before starting to code, let’s get some theory of what this is all about: what you first need to know about asyncing is that there are methods that are Thread-Safe and Non-Thread-Safe; this means that you may call a method on the main thread from your second thread but if the method is Non-Thread-Safe, you’ll get an exception. Normally, Thread-Safe methods’ names start with ‘Begin’ and ‘End’. Now, in the case we need to call a synchronous method asynchronously we need some method to call, a calling method and a Callback one; hereby an example:

Sub DoSomethingAtBackground()             ‘Calling method.

[…]

End Sub
Sub DoSomeStuff(ByVal Text As String)     ‘Method to call.

[…]

End Sub 

Sub Callback(ByVal ar as IAsyncResult)    ‘Callback method.

[…]

End Sub

The Callback method must have that signature for the CLR (Common Lenguage Runtime) to pass you the result of the async. call.

With that explained, we can now get into asyncing. To call a sync. method asynchronously we need three main objects: a Function Delegate that has exactly the same function signature as the method to call, an instance of this Delegate and a AsyncCallback delegate object; for example:

Delegate Sub DAsync(ByVal Text As String)

Dim del As DAsync = New DAsync(AddressOf DoSomeStuff)

Dim DCallback As AsyncCallback = AddressOf Callback

The AsyncCallback delegate references the method that will be called once the async. operation is completed.

In your DoSomethingAtBackground() method you should have at least the following to get asyncing. up:
 

del.BeginInvoke(“Hello World!”, DCallBack, Nothing)

In your Callback() method you need the following to correctly finish the call:

del.EndInvoke(ar)            ‘Always remember this.
 

Here I drop a simple example (this is a Console Project. You need to call DoSomethingAtBackground() from your Main() method):
 

Module Sample

Delegate Sub DAsync(ByVal Text As String)

Dim del As DAsync = New DAsync(AddressOf DoSomeStuff)

Dim DCallback As AsyncCallback = AddressOf Callback

Sub DoSomethingAtBackground()             ‘Calling method.

del.BeginInvoke(“Hello World!”, DCallBack, Nothing)

End Sub
Sub DoSomeStuff(ByVal Text As String)     ‘Method to call.

MsgBox(Text)

End Sub
Sub Callback(ByVal ar as IAsyncResult)    ‘Callback method.

del.EndInvoke(ar)                   ‘Always remember this.

Console.WriteLine(“Is task done? ” & ar.IsCompleted.ToString())

End Sub

End Module

Happy Asyncing!


Hernán A. Gatta

January, 2006

XAML...

I got into XAML (Extensible Application Markup Language) a few days ago. I downloaded and installed the WinFX SDK, the Windows SDK and the WinFX Extensions for Visual Studio 2005.

It is a ‘Wiring Technology’ that lets you descriptively set up your UI (WPF), Events and Properties; Networking Services (WCF), Data Binding (CLR Integration) and so on in an XML-looking experience. For most developers, XAML will be replacing the well-known Windows Forms Designer file. If you’re not a programmer, you could still find XAML useful as you can set up also 2D and 3D static or even animated graphics. For a developer’s example, let’s take a look at a little comparison:

VB Windows Forms Designer’s File:

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
    Inherits System.Windows.Forms.Form

    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing AndAlso components IsNot Nothing Then
            components.Dispose()
        End If
        MyBase.Dispose(disposing)
    End Sub

    Private components As System.ComponentModel.IContainer

    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.Button1 = New System.Windows.Forms.Button
        Me.SuspendLayout()
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(104, 108)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(75, 23)
        Me.Button1.TabIndex = 0
        Me.Button1.Text = "Button1"
        Me.Button1.UseVisualStyleBackColor = True
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(292, 266)
        Me.Controls.Add(Me.Button1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)
    End Sub

    Friend WithEvents Button1 As System.Windows.Forms.Button
End Class

 

XAML (pretty much the same thing):

 

<Window xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
   Name="Form1"
      Title="Form1">

      <Button Name="Button1" Height="23px" Width="75px">Button1</Button>
</Window>

Yes, XAML lacks Class Attributes…

For Graphical People:

<Canvas xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
      Width="400" Height="400"
        HorizontalAlignment="Center"
        VerticalAlignment="Center">
  <Path Stroke="Black" Name="Face">
    <Path.Data>
      <EllipseGeometry Center="200,200" RadiusX="100" RadiusY="100"/>
    </Path.Data>
  </Path>

  <Path Stroke="Black" Fill="Blue" Name="LeftEye">
    <Path.Data>
      <EllipseGeometry Center="160,160" RadiusX="10" RadiusY="10" />
    </Path.Data>
  </Path>

  <Path Stroke="Black" Fill="Blue" Name="PlainRightEye">
    <Path.Data>
      <EllipseGeometry Center="240,160" RadiusX="10" RadiusY="10" />
    </Path.Data>
  </Path>

 
<Path Stroke="
Black" Fill="Blue" Name="RotatingRightEye">
   <Path.Data>
      <EllipseGeometry Center="240,160" RadiusX="10" RadiusY="10" />
    </Path.Data>
    <Path.RenderTransform>
      <ScaleTransform CenterX="240" CenterY="160"/>    </Path.RenderTransform>
    <Path.Triggers>
      <EventTrigger RoutedEvent="Path.Loaded">
        <BeginStoryboard>
          <Storyboard>
            <DoubleAnimation Storyboard.TargetProperty="(Path.RenderTransform).(ScaleTransform.ScaleX)"
              From="0.5" To="2" Duration="0:0:0.5" RepeatBehavior="Forever" AutoReverse="True" />

            <DoubleAnimation Storyboard.TargetProperty="(Path.RenderTransform).(ScaleTransform.ScaleY)"
              From="0.5" To="2" Duration="0:0:0.5" RepeatBehavior="Forever" AutoReverse="True" />               

          </Storyboard>
        </BeginStoryboard>
      </EventTrigger>
    </Path.Triggers>
  </Path>

  <Line X1="200" X2="200" Y1="180" Y2="220"
        StrokeThickness="5"
        Stroke="Black"
        Name="Nose"/>

 
<Path  Stroke="Black" StrokeThickness="5"
              Data="M 160,240 A 75,100 0 0 0 240,240" 
              Name="Smile"/>    

</Canvas>


Conclusion:
better than GDI, isn’t it?

 

Happy XAMLing! 


Hernán A. Gatta

January, 2006

About DTA...

About the DTA's double attempt to initialize the CRT (C++ Runtime Library):

After a couple weeks waiting the Microsoft's answer to this tricky kind of ‘bug’, we got that there's an incompatibility in the AppCompat Layer in Windows when applied to the ‘explorer.exe’ (the basic Windows Shell). This Layer does an emulation that somehow maps the old Windows APIs to the new ones and lets you run apps. designed to run in older Windows versions. This is new to WXP. There's a defect in the AppCompat Layer that causes double initialization of the CRT. When ‘explorer.exe’ is set to use AppCompat shims, EVERY app. that is launched by it will inherit the same AppCompat settings, therefore, causing the app. to hang (as long as your program also initializes the CRT). This can be fixed by deleting the entry for ‘explorer.exe’ under ‘HKLM\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers’ in the Window's Registry. For this to take effect, of course, you'll need to either restart your computer or kill the ‘explorer.exe’ process and start it again.

 

Reference: 

Bug Details (other).

Bug Details (me).

 

Happy fixing!


Hernán A. Gatta