George Mamaladze

Just another WordPress.com site

Just launched new open source project QrCode.Net at http://qrcodenet.codeplex.com

Download binaries and application – 32K
Source code – 99K

Background

Recently I was looking for a .NET implementation of QR code generator. Most of components either use online services to generate and/or recognize QR code or the implementation was not “good enough” for my purposes. The most popular and very powerful Java implementation comes from google’s open source project code.google.com/p/zxing called ZXing (Zebra Crossing => Z=Zebra + X=Cross + ing).

There I found a one-to-one c# port of earlier version. The project is focusing on additional features and further development in Java so it seems that no one is taking care of c# branch.

Thus I have decided to set-up this project QRCode.Netqrcodenet.codeplex.com.

As a start point I took a straight forward c# port of google’s QR code implementation from ZXing project.
I wrote a wrapper around and a demo application which is able to generate QR code from text as you type and save it to file.

In addition it contains a very naive and simple implementation of Artistic QR code generation. At the highest error correction level it is possible to create artistic QR codes that still scan correctly, but contain intentional errors to make them more readable or attractive to the human eye, as well as to incorporate colors, logos and other features into the QR code block.

Using the Library

If you can not wait to try it out just download source or binaries and follow this short guide.

Download binaries and application – 32K
Source code – 99K

First of all add a reference to project or assembly _Gma.QrCodeNet.Encoding_ and import the namespace.

using Gma.QrCodeNet.Encoding;

Sample 1: Encoding text to QR code bit matrix and printing out the result to console:

            Console.Write(@"Type some text to QR code: ");
            string sampleText = Console.ReadLine();
            QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.M);
            QrCode qrCode = qrEncoder.Encode(sampleText);
            for (int j = 0; j < qrCode.Matrix.Width; j++)
            {
                for (int i = 0; i < qrCode.Matrix.Width; i++)
                {

                    char charToPrint = qrCode.Matrix[i, j] ? '█' : ' ';
                    Console.Write(charToPrint);
                }
                Console.WriteLine();
            }
            Console.WriteLine(@"Press any key to quit.");
            Console.ReadKey();

Tada !

Sample 2: Rendering QR code to graphics, let’s say to panel control with segment size of 5 pixel, blue on yellow and 10 pixel padding:

using Gma.QrCodeNet.Rendering;

</span>
<pre>            const string helloWorld = "Hello World!";

            QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.H);
            QrCode qrCode = qrEncoder.Encode(helloWorld);

            const int moduleSizeInPixels = 5;
            Renderer renderer = new Renderer(moduleSizeInPixels, Brushes.Blue, Brushes.Yellow);

            Panel panel = new Panel();
            Point padding =  new Point(10,16);
            Size qrCodeSize = renderer.Measure(qrCode.Matrix.Width);
            panel.AutoSize = false;
            panel.Size = qrCodeSize + new Size(2 * padding.X, 2 * padding.Y);

            using (Graphics graphics = panel.CreateGraphics())
            {
                renderer.Draw(graphics, qrCode.Matrix, padding);
            }

Sample 3: Using out-of-the-box WinForms control. Just drag & drop it to your form an set Text and AutoSize property:

Sample 4: Saving QR code to file:

            QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.H);
            QrCode qrCode = qrEncoder.Encode("Hello World!");

            Renderer renderer = new Renderer(5, Brushes.Black, Brushes.White);
            renderer.CreateImageFile(qrCode.Matrix, @"c:\temp\HelloWorld.png", ImageFormat.Png);

Project TODOs and Plans

I think this project would be a good playground for:

  1. Understanding QR code form inside
  2. Designing and implementing efficient and elegant data structures and algorithms. I have looked at the ZXing codebase, especially encoding. The code is good, but there are still many things ti improve. Furthermore the automated Java to c# converter produced a lot of mess.
  3. Refactoring and rewriting code in a TDD manner – existing implementation can be used as an excellent refactoring initial point. In some cases I think I would prefer to rewrite and use old classes a reference implementations and run my test again both the old and the new code.

Parallel Programing, PLINQ and Globalization

I’m going to start with a simple code snippet which sorts an array of strings using LINQ.

IEnumerable<string> line = new[] {"Z","A","Ä"};
var result = line.OrderBy(letter => letter);
Console.WriteLine("{0}", string.Join(" ", result));

The result might look like this:

A Ä Z

… or not. It depends on the thread culture the sorting is running in. The string order is culture aware (unlike char order which is culture invariant), so if we switch for instance on one of the Norwegian cultures by adding this line Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("nn-NO"); before calling sort, we will get following output instead:
A Z Ä

As next I extended my code snippet to create 4 arrays and sort each of them parallely.

Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("nn-NO");
Console.WriteLine("Main thread-{0} \t Culture-'{1}'", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.CurrentCulture);
Console.WriteLine(new string('-', 80));

List<string[]> list = new List<string[]>();
for (int i = 0; i < 3; i++)
{
    list.Add(new[] { "Ä", "A", "Z" });
}

var result =
    list
        .Select(
            line => line
                .OrderBy(letter => letter));

Parallel.ForEach(result,
    line =>
        Console.WriteLine(
            "Thread-{0} \t Culture-'{1}' \t {2}",
            Thread.CurrentThread.ManagedThreadId,
            Thread.CurrentThread.CurrentCulture,
            string.Join(" ", line)));

Console.WriteLine();
Console.WriteLine("Press any key to quit");
Console.ReadKey();

The result looks like this:

Main thread-1    Culture-'nn-NO'
------------------------------------------------

Thread-1         Culture-'nn-NO'         A Z Ä
Thread-5         Culture-'de-DE'         A Ä Z
Thread-3         Culture-'de-DE'         A Ä Z
Thread-4         Culture-'de-DE'         A Ä Z

Press any key to quit

Line 4 sorting order differs from line 5. The sorting was splited up into 4 threads one main and 3 new threads.

All three newly created threads got the default culture of my system – not the culture of the main thread which was set manually.

The culture is a property of the executing thread. When a thread is started, its culture is initially determined by using GetUserDefaultLCID from the Windows API. There is no way that I know manipulate this. See CultureInfo.CurrentCulture property at MSDN.

The same result if you use PLINQ syntax:

    list
        .AsParallel()
        .Select(
            line => line
                .OrderBy(letter => letter))
        .ForAll(
            line =>
                Console.WriteLine(
                    "Thread-{0} \t Culture-'{1}' \t {2}",
                    Thread.CurrentThread.ManagedThreadId,
                    Thread.CurrentThread.CurrentCulture,
                    string.Join(" ", line)));

The same query without parallel execution delivers consistent output, all four sequences are sorted in the same order.

The solution is to pass a specific culture aware comparer across into the OrderBy method.

var norvegianIgnoreCaseComparer = StringComparer.Create(CultureInfo.GetCultureInfo("nn-NO"), false); 
list
    .AsParallel()
    .Select(
        line => line
            .OrderBy(letter => letter, norvegianIgnoreCaseComparer))
    .ForAll(
        line =>
            Console.WriteLine(
                "Thread-{0} \t Culture-'{1}' \t {2}",
                Thread.CurrentThread.ManagedThreadId,
                Thread.CurrentThread.CurrentCulture,
                string.Join(" ", line)));

Well, but what about foreach and LINQ legacy code which can be paralelized with simple replacement of a single line by Parallel.ForEach() or adding AsParallel(). The result might be unpredictable and difficult to figure out. So if I would be the author of .NET or PLINQ I would take over the culture of the main thread into the child threads, thus the data come from the main thread, the split-up takes place implicitly and in most cases results are merged back into the main thread back to be consumed there.

Similar issues might occur in queries using any of culture aware calculations, for instance DateTime formatting and parsing.

So if you are targeting systems having different regional settings it is a good idea to pass CultureInfo or Culture specific staff (like comparers) into every PLINQ query and parallel call.

Edulinq an excellent LINQ+TDD guide

Recently I stumbled across a question on stackowerflow.com about Edulinq. Its a series of blog posts turned at the end into a free eBook. Downloaded to my eBook reader and had a lot of fun in subway.

There where not to much to discover inside of LINQ for me, but it could help a novice to understand the LINQ “magic” and use it efficiently.

Another very important point for me was the test driven approach. You could take this book as a guide for test driven design and development.

Reading this book chapter after chapter you will see how TDD helps you to come to a best API decision when working on a library. It demonstrates that on sometimes you should compromise functionality or performance to increase usability and maintain necessary level of protection.

Every chapter follows the same structure contains a lot of test and productive code, builds on top of the previous and makes a basement for the next one – remembers me the double linked list.

A must to read book for TDD + LINQ fans.

Why .NET LinkedList does not support Concat and Split operations?

Download SimpleLinkedList source code

Concat O(1) or O(n) ?
The .NET LinkedList is a circular doubly linked list, where each node holds a reference to its previous and next nodes. The last node’s next is the head node and the head node’s previous is the last one.

Linked lists are attractive because of O(1) insertion and removal operations. Instead of shifting elements in array you just chain nodes in appropriate order and that’s it.

Following this logic concatenation of two lists should be similar O(1) operation. You just bind the end of the first list with the head of the second and let the both ends of the resulting list point to each other.

Nevertheless if you look at .NET LinkedList implementation you will find out that the only way to join two linked lists is to add elements of the second list one by one to the first one. This is O(n) operation.

Implementing Concat
So if you look at the implementation you will find out that the LinkedListNode has one more field except prev and next. This is a reference to the owner list. So with this implementation even if you implement concat in O(1) as described above, you will still need at least reparent all nodes which is again O(n) operation.

Can we avoid referencing list in every node? Yes we can. We can rewrite Previous and Next properties like this.

Before:

        public LinkedListNode Next
        {
            get
            {
                if ((this.next != null) && (this.next != this.list.head))
                {
                    return this.next;
                }
                return null;
            }
        }

After:

        public SimpleLinkedListNode GetNext(SimpleLinkedList list)
        {
            if ((this.Next != null) && (this.Next != list.First))
            {
                return this.Next;
            }
            return null;
        }

After removing parent checking exception handling code from LinkeList implementation you can implement contamination like this:

        public void Concat(SimpleLinkedList secondList)
        {
            if (secondList.m_Head == null)
            {
                return;
            }

            if (this.m_Head == null)
            {
                this.m_Head = secondList.m_Head;
            }
            else
            {
                var seamLeft = this.Last;
                var seamRight = secondList.m_Head;
                var newEnd = secondList.Last;

                seamLeft.Next = seamRight;
                seamRight.Prev = seamLeft;
                newEnd.Next = this.m_Head;
                this.m_Head.Prev = newEnd;
            }
        }

You are even able to maintain Count property correctly by adding counts of both lists.

this.m_Count += secondList.m_Count;

Drawbacks
The major drawback of this solution is that the second list is will be left in an inconsistent state after this operation. Its last.prev does not point to its head anymore. Another point is that any active operation on one of the lists will modify both, thus they have shared nodes. These side effects violate fundamental principles of OO design. So I can imagine that Microsoft won’t compromise at that point and decided not to implement concatenation.

What about Split?
Implementing Split is very similar, with the difference that you are not able to maintain Count property in O(1) time. You are splitting at certain node without knowing its index inside the list. So If you want to have a Split operation you should compromise Count property.

Concat extension method
There is a Concat extension method on IEnumarable interface. You might think it’s as stupid as Count extension method on IEnumarable and spends O(n) on bringing all together.

In fact it executes in O(1) returning a new enumerator which enumerates first list and jumps to the second when the first list reaches its end.
This might help if you are not going to continue working with concatenation result like with a LinkedList. Another point is that several subsequent concatenation operations cause nested enumerators. So you get a tree of enumerators over enumerators etc.

My implementation
The actual goal of my implementation of double linked list supporting concat and split was to try out and demonstrate test driven refactoring approach.

The first implementation was just derived from common .NET LinkedList.

    public class SimpleLinkedList : LinkedList
    {

        public SimpleLinkedList()
        {

        }

        public SimpleLinkedList(IEnumerable enumerable)
            : base(enumerable)
        {

        }

        internal SimpleLinkedList Split(LinkedListNode splitNode)
        {
            throw new NotImplementedException();
        }

        public LinkedListNode Find(T search, IEqualityComparer comparer)
        {
            return Find(search);
        }

        public void FindLast(T search, IEqualityComparer comparer)
        {
            return Find(search);
        }
    }

The second step was creating appropriate test set ensuring common LinkedList behaviour.

Example:

        [TestCase(new string[] { }, "A", new[] { "A" })]
        [TestCase(new string[] { }, null, new[] { (string)null })]
        [TestCase(new[] { "A" }, "B", new[] { "A", "B" })]
        [TestCase(new[] { "A", "B", "C" }, "D", new[] { "A", "B", "C", "D" })]
        public void AddLast_one_element_occururs_at_the_end_of_the_list(string[] original, string element, string[] expected )
        {
            var target = new SimpleLinkedList(original);
            target.AddLast(element);
            CollectionAssert.AreEquivalent(expected, target);
        }

After I had a reasonable set I started implementing functionality successively.
Here is the result – SimpleLinkedList

Advantages:

  • Less memory consumption, thus every node SimpleLinkedListNode has three pointers (prev, next, value) instead of four (prev, next, list, value) unlike original .NET implementation.
  • Supports Concat and Split operations in O(1)
  • Supports IEnumarable Reverse() enumerator in O(1) – by the way I do not see any reason why it’s not provided natively on the .NET LinkedList. Appropriate extension method requires O(n).

Disadvantages:

  • Does not support Count.
  • Concat operation leaves second list in an inconsistent state.
  • Split operation leaves original list in an inconsistent state.
  • You are able to share nodes between lists.

Other:

  • I have chosen an alternative strategy for implementing enumeration and find operations, rather than more verbose and purely readable original implementation. I hope the negative performance impact remains insignificant.

So be careful using this list and use it only if you are aware of consequences.

“Cancel me if you can” or PLINQ cancelability & responsiveness in WinForms

Download Source Code

Challenge

Just had the first chance to apply PLINQ (Parallel LINQ) to the real task.
When I am playing around with some new technology everything works fine, the real understanding comes along with challenges in a real use case. Currently I am working on application which processes large amount of text data gathering statistics on word occurrences (see: Source Code Word Cloud).

Here what the simplified core of my code is doing.

  • Enumerate through all files with *.txt extension.
  • Enumerate through words in each text files.
  • Group by word and count occurrences.
  • Sort by occurrences.
  • Output top 20.

Everything worked fine with LINQ. I wrote a prototype console application with a single LINQ query. … and ta-daa! Just adding one line turned it into PLINQ.

public static void Main(string[] args) {
    var result = Directory
        .EnumerateFiles(@"c:\temp", "*.txt", SearchOption.AllDirectories)
        .AsParallel()
        //.WithDegreeOfParallelism(1..63)
        .SelectMany(File.ReadLines)
        .SelectMany(ReadWords)
        .GroupBy(word =>; word, (word, words) =>; new Tuple<int, string>(words.Count(), word))
        .OrderByDescending(occurrencesWordPair =>; occurrencesWordPair.Item1)
        .Take(20);

    foreach (Tuple<int, string> tuple in result) {
        Console.WriteLine(tuple);
    }

    Console.Write("Press any key to quit."); Console.ReadKey();
}

private static IEnumerable<string> ReadWords(string line) {
    StringBuilder word = new StringBuilder();
    foreach (char ch in line) {
        if (char.IsLetter(ch)) { word.Append(ch); }
        else {
            if (word.Length == 0) continue;
            yield return word.ToString();
            word.Clear();
        }
    }
}

Finally all four cores of my PC and the fan where busy processing dozens of megabytes of free eBooks in my temp folder I have prepared for testing. Moving to PLINQ brought me significant performance boost. But adopting this one line into the WinForms application was a different challenge.

Frustration

… cancelability and responsiveness during long running queries were lost.

It seems that the OrderBy query was synchronizing data back into main thread and windows messages were not processed. In the examle below I am demonstrating my implementation of cancelation according to MSDN How to: Cancel a PLINQ Query which does not worked :(

public Form1()
{
    InitializeComponent();
    m_CancellationTokenSource = new CancellationTokenSource();
}

private readonly CancellationTokenSource m_CancellationTokenSource;

private void buttonStart_Click(object sender, EventArgs e)
{
    var result = Directory
        .EnumerateFiles(@"c:\temp", "*.txt", SearchOption.AllDirectories)
        .AsParallel()
        .WithCancellation(m_CancellationTokenSource.Token)
        .SelectMany(File.ReadLines)
        .SelectMany(ReadWords)
        .GroupBy(word => word, (word, words) => new Tuple<int, string>(words.Count(), word))
        .OrderByDescending(occurrencesWordPair => occurrencesWordPair.Item1)
        .Take(20);

    try {
       foreach (Tuple<int, string> tuple in result) {
            Console.WriteLine(tuple);
        }
    }
    catch (OperationCanceledException ex) {
        Console.WriteLine(ex.Message);
    }
}

private void buttonCancel_Click(object sender, EventArgs e)
{
   m_CancellationTokenSource.Cancel();
}

private static IEnumerable<string> ReadWords(string line) { ... }

I was not able to click Cancel button, move the form around, do anything at all until the whole query where finished. That’s was not the perfect cancelation behavior – “Yes you can cancel it but you can not click button which does that”. I have asked the question colleagues and posted at stackowerflow. Everyone gave me the same answer – call the query in another thread.
That was not an option form me, if I wanted to clutter my code with threading staff I would do it without PLINQ. PLINQ allows you to keep your logic free from parallelism / synchronization overhead keeping your code readable and closer to business not to techniques. (see proposed solutions at stackowerflow)

The Ahaa Moment

While waiting for THE expert’s opinion from somewhere in cyberspace I came up with my own which I like pretty much. I wrote these two extension methods:

public static class CallbackExtensions
{
    public static ParallelQuery<TSource> ProcessWindowsMessages<TSource>(this ParallelQuery<TSource> source)
    {
        return source.Select(
            item =>
                {
                    Application.DoEvents();
                    Thread.Yield();
                    return item;
                });
    }

    public static ParallelQuery<TSource> WithCallback<TSource>(this ParallelQuery<TSource> source, ISynchronizeInvoke target, Action<TSource> callback)
    {
        return source.Select(
            item =>
                {
                    Application.DoEvents();
                    Thread.Yield();
                    target.Invoke(callback, new object[] {item});
                    return item;
                });
    }
}

The first one just passes control to the main theread allowing standard COM and SendMessage pumping. The second one allows to invoke any action into the main therad with item argument which is currently processed. You can put them anywhere in your query depending how responsive your query should be. The example below passes control back to main after processing each file.

var result = Directory
    .EnumerateFiles(@"c:\temp", "*.txt", SearchOption.AllDirectories)
    .AsParallel()
    .ProcessWindowsMessages()
    .WithCancellation(m_CancellationTokenSource.Token)
    .SelectMany(File.ReadLines)
    .SelectMany(ReadWords)
    .GroupBy(word => word, (word, words) => new Tuple<int, string>(words.Count(), word))
    .OrderByDescending(occurrencesWordPair => occurrencesWordPair.Item1)
    .Take(20);

You can even use the second extension method to perform progress indication and staff like that. In my example I am showing every word processed in caption. Yes I know – this is highly inefficient but for demo purposes is ok. You can download my solution and play with position of the line. For instance putting it beside file query will show files in caption and will have moderate responsiveness.

var result = Directory
    .EnumerateFiles(@"c:\temp", "*.txt", SearchOption.AllDirectories)
    .AsParallel()
    .WithCancellation(m_CancellationTokenSource.Token)
    .SelectMany(File.ReadLines)
    .SelectMany(ReadWords)
    .WithCallback(this, word => { this.Text = word; })
    .GroupBy(word => word, (word, words) => new Tuple<int, string>(words.Count(), word))
    .OrderByDescending(occurrencesWordPair => occurrencesWordPair.Item1)
    .Take(20);

Negative effects

Using one of my extension methods you are creating a bottleneck bringing all of your parallel treads back into the main just to paint one word into form’s title bar. So the best solution would be to slowdown callbacks invoking into the main thread as much as possible. Let’s say you need to update a progress bar. It would be enough to do it 10 times in a second so put the timer and do not invoke again until appropriate time is elapsed after the last invoke. All other calls will just trivially return. Or you may decide to pass only every 1000-Th word to display on the screen.

Back to the roots: .NET binary search and the meaning of the negative number of the Array.BinarySearch() return value

Recently I gave a group of developers a task witch can be simplified to following simple problem: you have a sorted array of elements; find the index of a given element in this array. They came up with following solution:

//given array
int[] sortedArray = new[] { 1, 5, 8, 12, 18, 20 };
//Create a list from the array
List<int> list = new List<int>(sortedArray);
//use IndexOf method to find the element
int result = list.IndexOf(8);

Of course it works fine but didn’t we do too much work? Can we probably use the fact that the given array is sorted? Do we need an additional data structure List?

If we read the Performance Considerations section at MSDN class documentation we see that to perform IndexOf() operation the list first sorts the content and then performs the binary search on it. See: List<> at MSDN

So we can simply use the BinarySearch() method of the Array static class.

//perform binary search
int result = Array.BinarySearch(sortedArray, 8);

So the BinarySearch() does basically the same as the IndexOf() does, but quicker, sometimes it’s better to remember basic algorithms instead of using complex data structures to accomplish the very narrow task efficiently.

For more information on binary search algorithm see: Binary Search (Wikipedia)

Why does the BinarySeacrh() do more then IndexOf() does?

Let’s search a non existing element using both methods and compare results.

//given array
int[] sortedArray = new[] { 1, 5, 8, 12, 18, 20 };
//Create a list from the array
List<int> list = new List<int>(sortedArray);
//use IndexOf to find element
int result1 = list.IndexOf(17);
//Use Array.BinarySearch
int result2 = Array.BinarySearch(sortedArray, 17);

The result looks strange:

IndexOf(17)==-1
BinarySearch(17)==-5

Both of them deliver a negative value which should be interpreted as element not found. However in opposite to List.IndexOf() which always delivers -1 the Array.BinarySearch() returns some “magic” negative value. Following explanation can be found in class documentation:

Return Value : The index of the specified value in the specified array, if value is found. If value is not found and value is less than one or more elements in array, a negative number which is the bitwise complement of the index of the first element that is larger than value. If value is not found and value is greater than any of the elements in array, a negative number which is the bitwise complement of (the index of the last element plus 1).

For more information see: Array.BinarySearch Method (MSDDN)

Sounds complicated but means following: the binary search travels the binary tree, at some point it realizes that element can not be found and stops on a certain node. If you negate the result of the binary search and subtract 1 you will get the index of this element.

Index 0 1 2 3 4 5
Element 1 5 8 12 18 20

So if you search for 7 the result will be the negated index of element 8 minus 1, equals 2.

So if you search for 17 the result will be the negated index of element 18 minus 1, equals 4.

The formula is:

 - Array.BinarySearch(sortedArray, 22) - 1

Important: if you are searching for a value which is greater then the last element this formula gives you array length, which is a non existing index. So you should not use the result of this calculation to access an element of the array without checking if it’s less then length.

So if you search for 22 the result will be -7. -(-7) -1 = 6 = array length.

The return value of BinarySearch() can be used in wide range of algorithms. For instance when solving the problem of vertex collision detection. It might be useful also when working with text segments.

C# Tweaks – Why to use the sealed keyword on classes?

The sealed keyword is one of the very seldom used modifiers in C#. Probably most of you know what it is for, but many developers have not ever used it.

See C# Programmers Guide if you are not sure you remember what the keyword is good for: sealed keyword (MSDN)

Why shall I use it?

Most popular, but not really most important motivation is the performance – JIT compiler can produce more efficient code by calling the method non-virtually. I remember someone even made performance measurements, but I think that the real performance gain highly depends on algorithms in a specific use case.

The vast majority of .NET programmers let their classes “unsealed” without even considering making them sealed. If a class was not designedly made inheritable it is very probably even impossible to inherit from it and override members reasonably. On the other hand overriding members of the class which was not designed to be overridden might cause unpredictable results.

When a class is originally sealed, it can change to “unsealed” in the future without breaking compatibility.

Something new I’ve discovered recently

Recently I was refactoring some component with multiple classes making intensive use of inheritance. During cleanup I changed all leaf classes in inheritance tree, the classes which can not be inherited anymore, to be sealed. I was sure it will not break compatibility, but the next compile failed.

The reason was a bug, which became visible only after I made some class sealed to compile time. Not being sealed it would throw an exception during execution. This sample demonstrates the simplified version of this situation:

interface IInterface1 {}

class Class1 {}

class Program
{
   static void Main(string[] args)
   {
     //Class1 does not implement IInterface1
     Class1 instanceOfClass1 = new Class1();

     //However this cast does not leads to compilation error
     IInterface1 someImplementer = (IInterface1)instanceOfClass1;
   }
}

Class1 does not implement IInterface1, however the cast of an instance of the Class1 to IInterface1 does not lead to compilation error. The reason is that theoretically some inherited class of the Class1 might implement this interface.

Now let’s make Class1 sealed. Now the compiler will see that Class1 can be only Class1 “itself” (and its base classes if applicable) and it does not implement interface IInterface1.

internal interface IInterface1 {}

sealed class Class1 {}

class Program
{
    static void Main(string[] args)
    {
        //Class1 does not implement IInterface1
        Class1 instanceOfClass1 = new Class1();

        //However this cast does not leads to compilation error
        IInterface1 someImplementer = (IInterface1)instanceOfClass1;
    }
}

Following compilation error will occur:

Cannot convert type 'Class1' to 'IInterface1'

So using sealed keyword brings not only performance win and additional code access security but also helps to write bug free code, making better use of the .NET type safety.

My recommendation: Always declare a new class as sealed until you are writing an abstract class or a class which must be inherited per design. Most classes in a real application (except you are writing a widely used library) can be made sealed.

P.S. You can apply the sealed keyword not only to classes but also to some members. I am going to post about that as well.

Follow

Get every new post delivered to your Inbox.