No Anders & co didn't just add whatever they felt fashionable, they've designed a language over the course of a decade with (to my knowledge) zero warts, bringing to the table more than 20 years of prior design experience (Turbo Pascal, Delphi).
If it weren't for the stigma of being a Microsoft design, C# would be a hugely more popular language.
* Garbage collection
* Lightning fast compilation
* Pointer-safe subset good enough for most common uses.
LINQ is also considered a huge win by many, though I suspect it could also be done in C++.
I also find it nice that with C++/CX VC++ is offering what C++ Builder does for years in terms of C++ RAD development.
Nowadays most of the consulting projects I work on are in JVM and .NET land.
What I really wanted to say it that I would like to see NGEN and .NET JIT offer the same type of optimizations as VC++ does, like SIMD, auto-vectorization and such.
When targeting Windows Phone 8, .NET gets compiled to native code with such type of optimizations using a cloud based AOT compiler. Maybe those improvements will eventually be brought into the standard framework.
If you created a delegate (function pointer) to such a special function that hadn't been called yet, it'd point to the wrong place and let you do things that shouldn't be possible.
The neat thing is that the code was valid and verifiable (so it'd run in low-trust), but you'd still end up owning a function call to the wrong point of memory due to a runtime bug.
Like practically every CLR vuln, it's the loading platform that is affected, not the applications. I think it's only important when relying on the complicated sandboxing restrictions (CAS).
I'd like to publish a working example, but haven't had the time to figure out which old OS allows the specific old .NET version to replicate the behaviour. I only found it by accident and was more concerned about finding a workaround to not crash.
While I haven't used, the Xamarin iOS/Android development platforms look quite interesting. I suppose it has the stigma of a somewhat pricy per seat license but its likely worth it if you want to go with a shared codebase for iOS/Android/WP/Win8.
There's also MonoGame[1] which targets developers of MS's former XNA game dev kit.
There was definitely one that got me (they made a breaking change to fix it in C# 5.0, though).
http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closi...
I agree completely, though, that it is remarkable how well-designed the language is.
C# is a nice language, but oh man, is that asking for it!
My pet example of a wart is the set of requirements on the iterated collection in foreach loops. Most C# developers probably think that the collection has to implement IEnumerable, but it is not so! I pasted the requirements from the spec at http://pastebin.com/EfsAmz6f
This is also a case where the dynamic type does something different than the static type. If you iterate over a statically typed non-IEnumerable collection, it will work fine (assuming it implements the required methods). But if you then change the type to dynamic, I think you get a runtime error.
So there's a wart for ya!
Any idea why they did this? The only thing this seems to achieve is that you can implement IEnumerable and IEnumerator without explicitly stating it. Are there any (common) classes to which this applies?
But at that point it's just a regular method that might also happen to implement part of an interface that you the programmer are not using (at least at that point).
Likewise in the case of foreach, the compiler is looking for a particular method and does not need to care whether or not that method happens to also implement part of an interface, so there is not point in making the programmer go through the trouble of marking the type as such.
class Heh : IEnumerable {
public void Add(object x) { Console.WriteLine(x); }
public IEnumerator GetEnumerator() { return null ; }
}
static void Main() { new Heh { "a", 1, DateTime.UtcNow }; } }
Prints out: a, 1, 6/25/2013 4:51:38 AM,
It might have been the right engineering approach all things considered. But having these special things that only the language can decide is annoying. The fewer the language primitives, the better.Now you can argue whether it is better to just map to the methods Add<T>(T item), GetEnumerator<T>() and Dispose() or if you require an interface like IInitializable<T>, IEnumerable<T> and IDisposable. On one hand requiring an interface just adds some overhead, on the other hand it makes the intention much more explicit. They came up with different solutions for different cases - using requires the interface, foreach supports both ways and there is no interface for collection initializers.
I don't understand why foreach supports both ways - if I implement GetEnumerator() adding IEnumerable to the interface list seems no unreasonable requirement just like in the IDisposable case. I can understand that there is no interface for collection initializers because this feature was added in C# 3.0 and would have required adding an new interface to all existing collection classes, or changing interfaces or starting with an inconsistent implementation. Would be interesting to hear about the details of the decisions.
And arguably there are other languages which can and do fix that gap. Nemerle comes to mind. .NET allows you to mix languages freely so I think switching for parts where it makes sense isn't such a bad idea.
Still, great language, love it.
The stuff actually fits in the language pretty well. What has resulted, however, is that there are multiple ways to skin a cat in C#, and there's very limited guidance on what's considered idiomatic.
This is complicated by the fact that many .NET/C# shops have coding standards in place that don't go much beyond C# 2.0. The last C# interview I did, at an allegedly "progressive" .NET shop, the interviewer barred me from using null coalesce in a whiteboard example because "That's hobby project code. It's not how we write production code"
Great language, terrible culture.
I find C# to be much more idiomatic than C++ or Scala. If you think C# is bad...stay away from those languages.
I too had a boss (new owner after acquisition) say "no you're not allowed to use lambdas".
This is typical enterprise stuff, I bet most typical enterprise already making the switch to Scala and F# also force their developers to type annotate everything.
The consulting company I work for still gets requests for project in Java 1.4, for example.
My last .NET project we had some issues because there was a mix of .NET 3.5 and 4.0 across teams.
As far as I know dynamic was added to ease interop with native code - I have never seen it heavily used in regular code. LINQ and lambda expression have been introduced together with the Entity Framework and I am unable to imagine using an O/R mapper without something similar again - it just fits together so nicely.
Async was an obvious next choice - we are getting more and more cores and traditional thread-based parallel programming just does not scale because it is so error prone. And after they extended LINQ to PLINQ they had a good part of the necessary infrastructure already in place.
[1] For example they would like to add something like Java's checked exceptions but when they considered it they came to the conclusion that there are to many unsolved problems and that it might require a few more years of research to come up with a really good way to do it and so they postponed it for later reconsideration. In general there is a lot of well researched theory behind the things they do. Another example is the Entity Framework. They didn't just implement another O/R mapper but came up with a mathematical theory comparable to the relational algebra and then implemented it based on that results.
LINQ's another example of a place where the C# team sighted one end advantage (queries) and implemented the minimum to make it work. That's why all the features around the main LINQ part are half-assed (limited expression trees, ambiguous lambda syntax, very limited type inference.)
Overall, C#'s a nice enough language for a lot of projects. The tooling really helps sells it, too. It's just rather verbose and limiting, unnecessarily. I just can't think of any place where C# the language is significantly better than F#.
But, if you're ranking it against the likes of Java, then yes, C# is close to perfect.
Edit: C# implements a lot of stuff right into the compiler, things that'd be useful more generically. For instance, foreach and collection initializers use duck typing that's baked into the C# compiler. That's a generally useful feature, but again, hard coded for a specific scenario. F# has some of that too, but not to the same extent (F# warts arise mainly when you push the edge of F#-C#ish interop).
Currently my F# code is mainly for scripting when doing .NET projects, but only if I am the only user of such scripts, otherwise Powershell.
Anyway I really appreciate the work Microsoft puts on F#, Haskell and OCaml via their research arm.
Having FP concepts sneak in C# is easier to get them introduced in this world, than forcing this type of developers to use something like F#.
This why Erik Meijer decided the best way to bring FP to the enterprise was via Visual Basic.
http://research.microsoft.com/en-us/um/people/emeijer/papers...
I'm sure I'm not the only one who misses these features when they're working in Java.
I've been a c# developer for over 5 years and I have to disagree with almost everything you said. Ruby blew my mind when I learned it.