There was a thread internally on the virtues of using the managed extensions to C++ or using C#...   This is dangerous territory as they are both well supported by the CLR so I don’t feel like I should recommend one language over another.  Core to our “common language” message is that you can use the language you are most comfortable with.    

And I kow this could kick of a heated debate, but, I feel stronly that we should be getting as much information out to the community as we can.  Be aware that the statements below are personal opinions and not the "offical" Microsoft postion.  Here is my roll up of the discussion, I think many of the tehincal details here will be helpful for you as you decide what language to write in.   None of the views expressed below are necessarily mine... I will give you mine over a beer sometime ;-)

 

Question:

Assuming devs who don’t mind writing Monitor.Enter and Monitor.Leave instead of lock (and other such niceties) and think that explicitly calling box and unbox is a feature than a nuisance, are their any advantages to using C# instead of Managed C++ for code that does not care about being verifiable?

One advantage that comes to my mind is that the C# compiler may be better at the IL produced because C# is the preferred language of the platform. Is this valid? 

Responses:

No, this is not valid.  The C++ compiler actually uses the C++ optimizer to get a better IL before it generates the final IL that will be JITed.


MC++ is great for the times when C# doesn't quite make it. You can do a lot with runtime interop, but when you have a complex scenario, you can easily spend a day doing something in C# that would take you 30 minutes in MC++.

But outside of those times, I find C# to be straightforward and productive. I generally don't need to write a mixture of managed and unmanaged code, or explicitly box and unbox items, and I'd rather my language isn't complicated with those elements. I find that I can "flow" a lot easier in C# than I could in C++. 

A couple other comments on what others have said:

  • There is ramp-up time for both MC++ and for C#.
  • For many applications, it's not an either-or choice. You can choose to write part of the application in one language and part in the other. There are a number of C# teams that write a bit of interop code in C++.
  • Compilation speed may be an issue in your build lab and test scenarios, and the difference in raw speed is significant. Whether it matters once you've layered a bunch of process around the build depends upon your process.

One final comment. If your group is thinking about adopting one or another, you should find  other people using that language and ask them why they made the choice that they did, and what issues they've found.  Don't ask the language team guys.   

1) “C# can produce verifiable code”

>>So can C++, but unverifiable constructs are not required to be called out with an “unsafe” keyword. For a future release, we are adding a >>new compiler switch /clr:safe, which will emit errors on anything that is not verifiable. For 7.1, writing verifiable code take a bit

>> more effort, but it is still possible.

2) “C# has better type-safety for .NET code than C++. “

>> Verifiability implies type safety.

3) “C++ can lead to accidental use of unmanaged types in a managed way, which will cause memory leaks.”

>>True. But C++ has always been and will always be a low level power language. You need to know what you’re doing.

>>Both C++ and C# are both great ways to write code for .NET. Language choice always needs to be the result of careful consideration of >>design goals and the skills of the developers involved.

C# compiler is FASTER than C++. At least for the volume we are using.

 

If your project involves a non-trivial amount of interop, using MC++ is a no-brainer.  This is especially true if your code is interop-ing with pieces that are highly fungible, in which being able to include native headers, rather than redundantly defining your interfaces (or using a tool like tlbimp, which has its own set of problems discussed in the link below), gives you build robustness not achievable with any current C# technologies.  Even if you don’t think you’re going to be doing much interop, I would urge you to think things through carefully: I’ve seen many projects start out with C# assemblies only to find that they need a special MC++ “interop helper-assembly” later on.  Such projects not only mix managed with native, but also mix programming languages!  No matter what side of the language debate you’re on, I’m sure you’ll agree that the more languages you use in a project, the worse things get...

 

One key cost to consider is porting to 64bit environments is seamless with verifiable C# (i.e. you run the same image as we do with the entire .NET Frameworks on 64bit environments) but painful with mc++ as you have to recompile and such (as we are learning in porting Avalon). Be aware of this hidden cost.


I wouldn't recommend using managed C++ for any significant new library development unless your code is only for COM Interop or other purposes.  Perf anecdotes aren't interesting without looking a specific scenario, and I doubt there's a big difference between C# and managed C++ when doing useful things for a managed library via COM Interop.  After talking to the dev team about our Interop support in managed C++, this has only reaffirmed a little bit of my bias against managed C++. 

There are really 3 different ways you should think about calling the Win32 API's in managed C++. 

1) Unmanaged

Here, the compiler just emits whatever X86 is necessary to make a call to a Win32 method, same as in straight unmanaged code.  This has 0 marshaling support for managed data types.  You can use something like #pragma unmanaged in your code to make sections of your code completely native, etc.  It sounds very powerful, but a bit on the complex & limited side since you can't really use managed types here.

2) Goes through the managed marshaler, but uses unmanaged data types

By default if you try calling the Win32 API when using the /clr switch, the compiler makes essentially P/Invoke function prototypes for each Win32 API you include from a header file.  These go through the managed P/Invoke marshaling layer, but the methods are prototyped the same way they are prototyped in Win32.  So instead of a P/Invoke method taking a String reference or a StringBuilder, you instead have P/Invoke methods taking an LPCTSTR or LPTSTR.  This is a bit difficult for writing managed code – it can certainly be done, but you'll have to manually pin your managed String objects, etc.  (I believe there are some templates from the C++ team to help make this easier, but still, I wouldn't want to force myself to use them.)

According to Adam Nathan from our managed services team, there is one huge drawback here for anyone considering writing a library using this functionality.  By default the compiler generates prototypes that don't store the error code in an interesting place.  Because of this, you can't get useful information from Marshal.GetLastWin32Error().  Additionally, you can't P/Invoke to Win32's GetLastError because the CLR may call some other methods that call SetLastError while marshaling the return value or out params back to managed C++.  This sounds like it could be an issue for anyone who is seriously considering writing a library in MC++. 

3) Marshal managed data types

The third way of calling the Win32 API from managed C++ would be to define your own function prototype that does what you want.  In here, you'd definitely want to make sure the last error value is preserved, and you can use real managed data types in your prototype as well.  This is pretty important in my opinion – you get correct string marshaling for ANSI/Unicode systems, and you can use SafeHandle.  As you may know, SafeHandle is our reliable handle wrapper that guarantees you won't leak resources and solves a handle recycling bug that is pretty much all object-oriented, multithreaded sandbox environments will run into (like a JVM or user-written C++ running in something like ASP with some additional security restrictions, if such a thing exists).

COM Interop is supposedly easier in managed C++, but I don't want to use COM at all and fortunately it is not required for my job.  (Yes, we do a few things to support COM Interop, but we don't need to use COM in 99% of the BCL.)  I suspect the COM Interop support in C# is probably powerful enough and I can read Adam's book & the C# language spec to figure it out if I ever have to deal with it.

From my perspective library writers will always want to use #3 above.  Managed C++ does have a lot of power, but the most useful features are Interop support and slightly bizarre pointer manipulation things (such as a reference to a boxed value type like "boxed Int32 *" only with probably nastier syntax).  Given what I do, the Interop support isn't a win for me at all over C#.  There are some obscure things I'd like to do that I can't do in C#.  But C# is just so much easier to use, and I find managed C++ nearly unreadable. 

We had some other legacy things going on that affected the status quo:

* In V1 and V1.1, we didn't have a cross-language linker (al works but only produces multi-module assemblies which we wanted to avoid).

* On the BCL team, we have ~900 methods that call directly into the CLR to do tricky or internal things, and about 50 of those couldn't be written in C# because the language wasn't powerful enough.  Managed C++ would have helped us, but C# later added features that put it roughly on par with Managed C++.

From this, hopefully you can understand why the .NET Framework is written almost exclusively in C#.  (I think we have two exceptions – a Managed C++ dll for COM Interop custom marshalers, and I think there's one small piece written directly in IL but I don’t recall where.)  Given a cross-language linker, we might consider rewriting some isolated pieces in managed C++, but we haven't had a serious need yet to add this complexity to our build process.