Current version

v1.10.4 (stable)


Main page
Archived news
Plugin SDK
Knowledge base
Contact info
Other projects



01 Dec - 31 Dec 2013
01 Oct - 31 Oct 2013
01 Aug - 31 Aug 2013
01 May - 31 May 2013
01 Mar - 31 Mar 2013
01 Feb - 29 Feb 2013
01 Dec - 31 Dec 2012
01 Nov - 30 Nov 2012
01 Oct - 31 Oct 2012
01 Sep - 30 Sep 2012
01 Aug - 31 Aug 2012
01 June - 30 June 2012
01 May - 31 May 2012
01 Apr - 30 Apr 2012
01 Dec - 31 Dec 2011
01 Nov - 30 Nov 2011
01 Oct - 31 Oct 2011
01 Sep - 30 Sep 2011
01 Aug - 31 Aug 2011
01 Jul - 31 Jul 2011
01 June - 30 June 2011
01 May - 31 May 2011
01 Apr - 30 Apr 2011
01 Mar - 31 Mar 2011
01 Feb - 29 Feb 2011
01 Jan - 31 Jan 2011
01 Dec - 31 Dec 2010
01 Nov - 30 Nov 2010
01 Oct - 31 Oct 2010
01 Sep - 30 Sep 2010
01 Aug - 31 Aug 2010
01 Jul - 31 Jul 2010
01 June - 30 June 2010
01 May - 31 May 2010
01 Apr - 30 Apr 2010
01 Mar - 31 Mar 2010
01 Feb - 29 Feb 2010
01 Jan - 31 Jan 2010
01 Dec - 31 Dec 2009
01 Nov - 30 Nov 2009
01 Oct - 31 Oct 2009
01 Sep - 30 Sep 2009
01 Aug - 31 Aug 2009
01 Jul - 31 Jul 2009
01 June - 30 June 2009
01 May - 31 May 2009
01 Apr - 30 Apr 2009
01 Mar - 31 Mar 2009
01 Feb - 29 Feb 2009
01 Jan - 31 Jan 2009
01 Dec - 31 Dec 2008
01 Nov - 30 Nov 2008
01 Oct - 31 Oct 2008
01 Sep - 30 Sep 2008
01 Aug - 31 Aug 2008
01 Jul - 31 Jul 2008
01 June - 30 June 2008
01 May - 31 May 2008
01 Apr - 30 Apr 2008
01 Mar - 31 Mar 2008
01 Feb - 29 Feb 2008
01 Jan - 31 Jan 2008
01 Dec - 31 Dec 2007
01 Nov - 30 Nov 2007
01 Oct - 31 Oct 2007
01 Sep - 30 Sep 2007
01 Aug - 31 Aug 2007
01 Jul - 31 Jul 2007
01 June - 30 June 2007
01 May - 31 May 2007
01 Apr - 30 Apr 2007
01 Mar - 31 Mar 2007
01 Feb - 29 Feb 2007
01 Jan - 31 Jan 2007
01 Dec - 31 Dec 2006
01 Nov - 30 Nov 2006
01 Oct - 31 Oct 2006
01 Sep - 30 Sep 2006
01 Aug - 31 Aug 2006
01 Jul - 31 Jul 2006
01 June - 30 June 2006
01 May - 31 May 2006
01 Apr - 30 Apr 2006
01 Mar - 31 Mar 2006
01 Feb - 29 Feb 2006
01 Jan - 31 Jan 2006
01 Dec - 31 Dec 2005
01 Nov - 30 Nov 2005
01 Oct - 31 Oct 2005
01 Sep - 30 Sep 2005
01 Aug - 31 Aug 2005
01 Jul - 31 Jul 2005
01 June - 30 June 2005
01 May - 31 May 2005
01 Apr - 30 Apr 2005
01 Mar - 31 Mar 2005
01 Feb - 29 Feb 2005
01 Jan - 31 Jan 2005
01 Dec - 31 Dec 2004
01 Nov - 30 Nov 2004
01 Oct - 31 Oct 2004
01 Sep - 30 Sep 2004
01 Aug - 31 Aug 2004


Powered by Pivot  
XML: RSS feed 
XML: Atom feed 

§ First impressions of C#

I've long been a believer in tuning for speed and efficiency. Part of this comes from having used underpowered machines for a long time, and part comes from being very impatient. Some of this also comes from my early days of coding on various Microsoft-derived BASIC interpreters such as Applesoft and AmigaBASIC. (These aren't nearly as bad as, say, TI-99/4A BASIC, but you haven't seen a real interpreted BASIC until you've used AMOS Professional.) I did a little bit of 6502 assembly after that, some 68000, and then a bit of 16-bit x86 — painfully. And of course, after that, 32-bit x86. My language of choice nowadays however is very clearly C++, because of its expressiveness, power, and leanness.

Recently I've had the opportunity at work to write a bit of C# code. My first impressions of C# were somewhat tainted by my bad memories of Java 1.1, which seemed to combine a deliberately painful subset of C++ with a slow VM and an abysmally bad library. (Not to mention the IDE used by my school, Symantec Café, which we affectionally called Crapfé and which I fondly remember for its use of a listbox as an output window.) C# definitely stays a lot closer to C++ than Java did, and I think it is a better language for having done so. I would definitely not even consider rewriting VirtualDub in it at this point, but it's definitely a much more amiable language than most others in its class that I've seen.

I should note at this point that I've only tried the barest amount of C# 2.0; most of my experience so far is with C# 1.1 (VS2003), so bear with me if I complain about something that has already been fixed.


The C# designers seemed to have genuinely tried to fix some of the warts in the C++ language. It has override, so you can't screw over a subclass accidentally when modifying a method prototype. It has foreach and with. Reference parameters now have to be tagged as in, out, or inout so you know which way the data flows and the compiler can catch missing assignments. You have your choice between checked and unchecked arithmetic, so you can detect overflows in some code and still abuse integer math in others. It complains about variable names being reused in inner scopes, which while it drove me crazy when I was coding, is actually a practice I need to wean myself off of.

C# also includes a rudimentary form of the preprocessor, which I have mixed feelings about. I hated not having the preprocessor in Java, as it meant you couldn't easily guarantee that debugging code didn't ship in a release build. However, the C# preprocessor doesn't allow you to do much more than this, which makes it unusable for debug trace macros (very important). The preprocessor is also extremely useful for building data structures, tables, and cleaning up repetitive comparison tests in a readable manner. I will admit that some of these uses would better be served by direct language support, however; I'd like not to have to write the same ugly debug trace macros every time I start a new C++ project, and System.Diagnostics.Debug.WriteLine() is too long.

Support for pointers and unsafe code in general is also a nice plus, and is something that I consider essential for a real-world Win32 application. The stackalloc keyword, which is a more formal version of alloca(), is really cool. Contrary to popular opinion, virtual machines that execute code in a safe manner do still impose a performance penalty, and in particular anything that deals with large arrays, such as image and audio data, takes a noticeable performance hit from bounds checking. Being able to just mark a routine as unsafe and do C++-like pointer arithmetic to close the gap is great.

One thing I don't like, though, is the removal of separate declarations and definitions for classes. I hated this when I was using Java and I still find it a bad idea in C#. The main problem is that it makes it very difficult to present the direct API of a class that doesn't implement a separate interface, such as a value type. While a declaration in a C++ header is more work to maintain, it's very easy to scan. It's true that modern IDEs can collapse the class and only present the prototypes, but this usually ends up being badly formatted and doesn't allow you to order the methods differently in code and in header, which I often do for organizational reasons.

Coding in C# also seemed more verbose than C++ due to the longer, namespaced names of the standard classes in the .NET Framework. While it takes time to learn the names and headers, I find std::vector<> much less intrusive than System.Collections.ArrayList, and using defeats many of the benefits of namespaces. I also found that attributes in particular tended to be repetitive and long, especially when doing interop, and was wanting for a shorthand way to apply the same attribute to multiple items, or preprocessor support for doing so myself. Frankly, I appreciate that in C++ I only have to type std::max<> instead of something like Standard::Math::Max() and suggest that you don't need whole words for a name to be readable, particularly for something as common as the System namespace.


I didn't attempt to actually write a whole application in C#, but one of the things I ended up doing in it was to write a routine to weld vertices in a 200,000+ vertex 3D mesh. This was in the middle of an interactive tool for display purposes, so it was important that this execute as quickly as possible. The performance was abysmal compared to the C++ routine. I won't quote numbers, since I'm not supposed to and I don't have hard data anyway, but it was definitely noticeable, as in the C# routine was slow and the C++ one wasn't. It's important to note that most of this penalty centered around my use of a ulong-to-ulong Hashtable, which performed very badly compared to STL due to its need to box and unbox both key and value (leading to intense heap activity), call generic comparison routines through interfaces, and worst of all, the requirement to do a redundant second lookup for a read-modify-write operation. Most of these issues theoretically go away with the introduction of generics and generic containers in STL.NET, but I wonder if the last issue can be fixed, as the C++ solution requires references to a value type. In the end the routine was fast enough to use, but I still had a Zawinski-like urge to yet again write my own hash table.

I will note in passing that I really, really, really, really enjoyed having a foreach control structure and can't emphasize strongly enough to the C++ standards committee and Microsoft Visual C++ leads that we need typeof or decltype NOW.

In general, C# felt fast enough to use for routines that didn't have to process a 2MB vertex buffer, and definitely didn't feel as sluggish as Java did when it was introduced. However, as is usually the case, my views of performance at the low-level innards didn't seem to generalize to the whole-application level, as the application itself still felt a little sluggish — perceptably, not just that it was slower than native code. In general, I've seen very few applications written in JITted, garbage-collected languages that didn't feel slow, one of the notable exceptions being Azureus on Windows. I think this is primarily due to UI toolkits, which in the .NET case is Windows Forms, and with Java 1.1 was the AWT (Awful Windowing Toolkit). Using the unaccelerated GDI+ for drawing probably doesn't help, either.

I've tried to come up with excuses for writing some little utilities in C# just to get more familiar with it, but it seems that every time I come up with better reasons to do it in C++, probably because I'm so much more familiar with it and because STL is just too handy. That property grid control, however, makes it very tempting. I've also toyed with the idea of rewriting Filter Factory so it compiles to .NET bytecode instead, but I don't know enough about .NET bytecode or the Framework facilities for dynamic code to know if this is feasible.


Comments posted:

Have you looked at the Boost FOREACH library ( )? It's not quite as nice as having a native language element, but it's awfully close. Even more interesting to C++ junkies like myself is how it works. ( )

MikeL. - 01 07 05 - 19:01

Yuck. I love template/macro hacking as much as the next guy, but that's a bit too much — and I absolutely despise the idea of putting iterators in the heap. When you start abusing templates to this level, you (a) start seriously bloating your .obj files and compile times, and (b) risk breaking the compiler. I'm still sticking it out until VS2005 is shipped, and unfortunately VC6's template support is rather incomplete.

Phaeron - 03 07 05 - 16:33

C++ STL has the for_each keyword. However i always write a regular for-loop myself.

Peter - 04 07 05 - 14:08

I gave up on C# for now. Maybe .net 2 will make the language worth it. Every time I tried it out, it fell short and I had to call a WIN32 API to do what I wanted. What's the point then if it does not make life easier?
I understand that it's a limitation of .Net rather than C# but they are linked. I found Java richer, but sluggish.

Nick - 04 07 05 - 17:17

I’m glad you finally got round to trying out C# Phaeron. I was doubtful when I first heard of .NET as well. Now I do all my programming in C#. I just love to be able to focus on the important things rather than on nasty memory management and so on. As for you Nick I have to say that .NET does provide most of the functionality a programmer could think of. Of course there are some (even if they are few) things that it does not provide, so that you have to drop down to Win32 API calls, but that doesn’t really occur often in my programs. You sometimes just have to search a little for the proper .NET equivalent.
Phaeron, in your post you wrote that you are not considering to rewrite VirtualDub in C#, are you sure that this is a wise decision, taking into account that the main API in Longhorn is going to be WinFX and not Win32?

tommazzo (link) - 04 07 05 - 18:17

Microsoft will begin trying to migrate everyone to WinFX starting with Longhorn, but Win32 will absolutely be the primary API for Windows client-side development for quite some time, if for nothing other than that the existing 98/2000/XP market base is too big. For me to even begin considering a move I would have to see actual real advantages beyond "it's the new API."

I should note, as well, that at one I point I did recompile VirtualDub into managed C++ using Visual Studio .NET 2003. The compiler must have generated quite a mess of IJW thunks in order to get some of the hairier code to work, but it did run, although at a 10-20% speed loss. I wouldn't need to rewrite VirtualDub into C# to access .NET APIs; merely doing some interop into managed C++ code would be sufficient.

Phaeron - 04 07 05 - 21:00

Some things I found out very fast about C#:

1. ListViewItems have properties for things nobody needs. But if you want to save a simple id in it you have to subclass it.
2. ColumnHeaders have nothing. Not even an Icon to show the current sortorder with. You have to use API.

some really bad joke in C#:

if ("Hello, world." == (string)myobject)
- throws an invalid cast exception
if ("Hello, world." == ("" + myobject))
- works very well (looks like vb to me?)
if ("Hello, world." == myobject.ToString())
- works, too (but it just doesn't look like c/c++)

McMurmel - 06 07 05 - 11:06

Yes, the Windows Forms controls are still a bit lacking, because they are based on the Win32 common controls, which themselves have a lot of idiosyncracies. ListView in particular is an absolute pain to use native-side because every operation requires you to fill out a struct. What surprised me the most is that WinForms doesn't seem to have any formatted text control better than RichEdit, which is terrible — mainly because it is so hideously slow at formatted insertions.

As for the string comparison issues, those are the result of not having return-context-sensitive overload resolution. Once you've encountered the issue in C++, where strings are solely a library feature, the reason becomes clearer: your only choices are to overload operator==() both ways for stringobject compares (very annoying), or to implement an automatic implicit conversion from each object to string (very dangerous). Your particular issue generally isn't too much of a problem in C++ because there are often better ways to accomplish the task, such as implementing a string pool and doing comparisons against interned string handles instead.

Phaeron - 07 07 05 - 01:17

While I do get your point about the current Win32 client base I think that you also have to admit that you wouldn't start a new major application with the Win32 API. And if you wanted to stay on the native, unmanaged side I think that a toolkit like wxWidgets would still be a better idea than the Win32 API.

tommazzo (link) - 07 07 05 - 07:20


if think that the power of C# is the better reading, and the easier way to build applications. I would appreciate to rebuild virtualdub in C# and make some nice interfaces to write plugins. If you ever will do it, then I will help you to make the virtualdub software easier to use... and easier to extend...

this software is the best video software tool that I've ever seen...

Andreas Rudischhauser - 07 06 07 - 11:38

Comment form