A few things from C++ that i miss in C#

The last 6-7 months i’ve been working mostly with C# and to be honest I’ve grown found to it. It has really nice features like lambda expressions,   auto properties, extension methods, LINQ witch can really speed up things in terms development time.

Still … there are some things from C++ that i now miss: Templates ( as in true generics ) , const correctness, deterministic destruction, static initialization and most of all the control over what is a value and what is a reference.

Generics ( Templates )

Yes, C# has generics witch give you a level of freedom and ability to write generic code but they are nothing compared to the power of c++ templates. In C++ templates are compiled when instantiated and you don’t need to specify any constraints on the  generic type and as long as the instantiated type is syntactically correct your code will compile. There are ways to define concepts witch can impose requirements on the types but the concepts are also verified when the template is instantiated. Also C# does not allow specialization or partial specialization of generic types.

Const Correctness

There are a lot of articles on the web about why C# does not implement const correctness. In the end you learn to leave without it but its a nice thing to have and as long as you use it consistently it can help prevent a lot of bugs mostly design bugs. I guess that there are ways in C# to prevent the bugs that const correctness prevents  ( immutable objects, ReadOnly interfaces ) but they are harder to impose on a team of developers.

Deterministic Destruction

I’m quite sure that I only miss this feature because i come with a C++ background. You can easily have deterministic destruction in C# by using IDisposable and using(…) features, still after years of C++ i kinda like to know when an object gets destructed.

Static Initialization

To be honest I don’t miss this feature too much. The only thing i find it useful for is implementing the factory pattern where objects register themselves in the factory using static initialization. The downside of this is that it can relay get messy ( hint Static Initialization Fiasco )

Control over what is a value and what is a reference

Now this i miss the most. I have to admit it I like pointers. Well i actually like smart pointers and i like being in control of what and how i pass as arguments to methods. In C# it’s written in stone: structs are values and classes are references (ok, with boxing you can have references to structs but that’s not the point ). One of the problems is that there is no way of declaring a method that accepts a CONST reference to an instance. When you pass an instance of a class to a method (you actually pass the reference to that instance) , the method has full control over the instance.  This might not be a problem when you write all the code, but in a team with developers of different skill bad things can happen. Add some multi-threading to this and things can get relay messy. Another problem is when you have a value object implemented as a struct that is holding a lot of data and you need to pass this object to a Method that only needs to read something from this object. If you pass it as a value object it will probably get copied ( i’m not sure if the compiler does not implement some copy-on-write here but i would not relay on that ) and if you pass it as a ref than the method might change the data.

In conclusion I like working with C# but there are some things that i hope will get better in time. Other important ”bonuses” you get with C# are the .NET Framework and Visual Studio IDE that speed up substantially the development. The major downsite witch in some cases is a showstopper: Platform Dependent. I don’t know where MONO is right now but if you develop with C# and .NET you better make sure your main target platform is Windows.

I would be glad to hear what others think about this.

  • Lior

    I vote for deterministic destruction as the #1 missing feature. I even thought of a simple solution that can live side-by-side with the garbage collector (MICROSOFT, READ THIS): we should have had the option to tag classes with some [RefCount] attribute (maybe [AutoDispose] is a better name). The compiler/framework could have used this info for deterministically destructing (e.g. calling Dispose) objects of these class when their ref count reaches zero (clearly, managing ref count for these classes should be supported by .NET). Now you ask, what about cyclic graphs? If somebody is stupid enough to create a cyclic graph with [RefCount] objects, these objects will have to wait for their finalizers to be called, or the code should call Dispose explicitly- this is no different than the existing situation.

    Beside much easier management of unmanaged resources, The [RefCount]/[AutoDispose] solution would be extremely useful for well-encapsulating high-level activities, e.g. application-level protocols/sessions that need to be closed properly by actively transmitting data over the network.

    Today the situation is that callers that are not aware of the internals of the Dispose implementation frequently don’t call it. besides the issue that Dispose is called late (from the finalizer), it also doesn’t have guaranteed access to the reference-type properties in the class so, e.g. in the above application-level session example, it might not be able to transmit the session-close data over the network at all.

    This is a semantic flaw that became a standard with the courtesy of .NET, and it’s time to fix it.

  • http://www.erata.net eti

    Hi, thanks for the comment. As i said in the article i don’t mind that much the lack of deterministic destruction as long as i have a way of still expressing it – the Dispose pattern.

    Now about your suggestion of using some attributes to have reference counted objects witch get disposed immediately when the ref count is zero … i think this can probably be easy implemented at language level, but i don’t think it would have much value. If a [AutoDispose] object is a member of an “normal” reference object that it’s lifetime will be dependent of the lifetime of the managed object.

    What i would like to have ( and it’s something i still have to give some thought ) is a wrapper that would bound an instance to it’s scope and guarantees that the object is disposed/finalized when it gets out of scope. Writing the last line i realized that that’s what IDisposable is supposed to accomplish. I’ll have to think this one a bit before continuing…

  • Lior

    Your comment re “standard” managed objects controlling the lifecycle of [AutoDisposed] objects is correct. I believe that in order for my idea to work, a proper implementation will have to implicitly propagate the reference counting to any class that has a reference-count member (clearly, there may be exceptions). In fact, this is what we have to write explicitly these days- any class that contains an IDisposable member should (for reasons of proper encapsulation) implement IDisposable itself, even if all its Dispose method does is calling its IDisposable members’ Dispose methods. My idea will automate this process and exempt programmers from the burden of writing and managing the explicit calls to all these Dispose methods.

  • Allon Guralnek

    Eti, I think the disposing of object when out of scope is a good idea. Today I would have to write:

    private void CompressServerLog()
    {
    using (FileStream file = new FileStream(@”C:\archive.zip”))
    {
    using (ZipFileStream zip = new ZipFileStream(file))
    {
    zip.AddFile(@”C:\ServerActivity.log”);
    }
    }
    }

    Instead, I would like to write:

    private void CompressServerLog ()
    {
    using FileStream file = new FileStream(@”C:\archive.zip”);
    using ZipFileStream zip = new ZipFileStream(file);
    zip.AddFile(@”C:\ServerActivity.log”);
    }

    And have it translated to the first example by the compiler. Allowing the ‘using’ statement to be an optional prefix for local variable declarations which would tell the compiler to dispose when out of scope would be quite a nice feature in my opinion. That would actually make using the curly brackets to create an inner scope actually useful for a change.

  • Jesse

    @Allon

    In fact, F#, the new language being developed by Microsoft Research (origins in OCaml) has exactly the prefix syntax you want. Below is an example of the function you gave in F#’s syntax:

    let CompressServerLog() =
    use file = new FileStream(@”C:\archive.zip”)
    use zip = new ZipFileStream(file)
    zip.Addfile @”C:\ServerActivity.log”

    The filestream and zipfilestream’s are disposed when the function ends and the two ‘use’ bindings go out of lexical scope. Lexical scope is created by indentation or optional syntax a la:
    use file = new FileStream(…) in where the binding is scoped to the expression after the in keyword.

    You can read more about F# at fsharp.net
    http://msdn.microsoft.com/en-us/library/dd233240(VS.100).aspx has information on the ‘use’ binding and ‘using’ function.

    I’ve been using F# now for a year and am quite pleased with it. If you enjoy using LINQ, then you’ll love F#.

  • Allon Guralnek

    I like a little poppy seed sprinkled on my bread roll, but I thoroughly dislike poppy seed cake. Too much of a good thing (functional programming) can be, well, too much. Nevertheless, I’d try F# if it weren’t for the real world. You see, the job requirement is to write in C# and to target the .NET Framework 2.0. Thankfully, that means I can use all of C# 3.0′s features, including LINQ to Objects (with the aid of LINQBridge: http://code.google.com/p/linqbridge/). Since having a using prefix to local variable declarations is pure syntactic sugar, it would still work with .NET 2.0, just like the rest of C# 3.0′s features. Well maybe it will appear in C# 5.0 (by then I’m sure I’ll be using .NET 3.5 in production environment, still a little shy from the required .NET 4.0 for official F# support).

  • http://smellegantcode.wordpress.com Daniel Earwicker

    Lior, your suggest about reference counting is way off.

    VB 6 worked like that, and so obviously Microsoft considered very carefully if there was a way to bring it into .NET, and all that debate was played out nearly a decade ago. Here’s the conclusion that was posted to the original .NET mailing list back in 2000:

    http://blogs.msdn.com/brada/articles/371015.aspx

    One important point is that reference counting is NOT deterministic destruction.

    The whole point of deterministic destruction is to be able to say with certainty that by the time control reaches a certain point in the code, a certain resource has been freed. But if somewhere else in the program is able to stop that from happening, then it is invalidated.

    If you want deterministic destruction, you don’t want reference counting. You want C++ destructors (no reference counting) or IDisposable (no reference counting) or the Lisp/Schema “with” idiom (no reference counting).

    Reference counting is typically a wrong-headed attempt to simulate a GC where a proper automatic GC is not available. The irony is that GC is usually missing from the environment due to “performance concerns”, and yet the alternative chosen usually runs slower than automatic GC. This is certainly true with reference counting.

    Here’s a paper about an attempt to provide “deterministic” destruction via reference counting (which is a contradiction-in-terms):

    http://bit.ly/1OHefw

    They were surprised to find that C# programs ran an awful lot slower when using reference counting instead of GC. But if you understand just how amazingly fast the CLR’s GC is, this will not be a surprise.

  • http://www.shanghai-software.comblog Ben

    ref counting GCs were tried but performance penalty is heavy ( it also requires recompilation).. Cyclical references have been shown to always happen and are nasty bugs to find or test for.

    However you can manage your own memory by using a factory and pointers ( allocate a byte block) in an unsafe block and manage your own heap. This is very useful for cases when you want no GC collections eg if you were writing a 3D app and want to manage your vertex buffers etc. I

    Templates i can understand but few people actually understand some templates and Java passes with very poor generics.

    My biggest gripes
    -Non nullable types (Sing# has these)
    -Immutable object support via an interface

  • http://www.erata.net eti

    @Daniel: Thanks for the links, very informative on the subject.

  • http://www.erata.net eti

    Hi all,
    Funny thing that after this discussions i had an interesting debate at work. We are working with a DAL implemented using LINQ to SQL. Basically we have an MVC app that has Controllers witch use Services witch use Repositories witch use a LINQ DataContext.

    Now the DataContext generated by LINQ implements IDisposable, and when i see a class that implements IDisposable i want to play nice and dispose any instance created. The problem is that all the repositories share – for a request – the same DataContext instance and also the results of some linq queries are stored in cache so i can’t really dispose of the DataContext at the end of the request since objects created by it might still exist in the cache and they hold a reference to the DataContext.

    Going deeper in the DataContext story I’ve found out that you don’t really have to dispose it since it will not keep the db connection open only the while executing the query and retrieving the results. So in the end the conclusion was that it’s better, simpler to just leave it to the GC.

    Still it feels strange to rely on the internal details of the DataContext … but i guess it’s one of the prices i have to pay for all the nice things that LINQ to SQL brings.

    @Ben: Man, i hear you on the non nullable types.

  • Allon Guralnek

    @eti, you should not use a long-living DataContext, ever! You might have a long-living IDbConnection, but beware that a DataContext can leak memory like crazy. A simple test would be to try and insert a million rows. You’ll hit a OutOfMemoryException pretty fast, since the DataContext tried to track all the objects. The DataContext should be used on a per-operation basis, it’s a lightweight object – create it and dispose of it at the end of a logical operation. Use the constructor that accepts a IDbConnection object to avoid connecting and disconnecting from the database with each operations.

    In general, LINQ to SQL is a pretty basic and O/R Mapper, providing a very low level of abstraction. I suggest having a look at Entity Framework v4 which is included with .NET 4.0/VS2010 (EFv3, included with .NET3.5 SP1, what a bit… meh).

  • http://www.erata.net eti

    @Allon, thanks for your opinion on this. I have since than entered the world of NHibernate witch i can’t say i fully know, but witch has proven to be pretty complex and feature-full ORM. I’ve read about EF 4 and i’m eager to play hoping that will be a log more than v3 was.