views:

4455

answers:

32

What do you think are the biggest design flaws in C# or the .NET Framework in general?

My favorites are that there's no non-nullable string type and that you have to check for DBNull when fetching values from an IDataReader.

+9  A: 

Some people (ISVs) wish that you could compile it to machine code at build time, and link it, in order to create a native executable which doesn't need the dotNet run-time.

ChrisW
You should be able to NGEN your program before running.
Otávio Décio
Not the same as removing dependencies of the runtime. You only save the first JIT run over your code.
Ed Swangren
See http://www.yoda.arachsys.com/csharp/faq/#framework.required
Marc Gravell
Isn't there an obfuscation tool which does this? It will embed the framework in your exe so you don't have to deploy it. I can't rember it's name...it's not PreEmptive's...
JoshBerke
Doesn't Xenocode's Postbuild do that? It would be nice if Visual Studio had a way to do this...
BenAlabaster
Yeah and how expensive is Xenocode? IF some third-party company can build it, what's preventing MS from building it and making it a part of VS?
Cyril Gupta
Mono has a linker...not tried it with .NET: http://www.mono-project.com/Linker
Mark Brackett
Xenocode is very reasonable for all its features. About $400. With a 30 day trial I think.
jcollum
strangely enough, Mono does this! http://tirania.org/blog/archive/2008/Nov-05.html
gbjbaanb
I thought you could NGEN during installation? I may be wrong...
Christian Hayter
+59  A: 
  • the Reset() method on IEnumerator<T> was a mistake (for iterator blocks, the language spec even demands that this throws an exception)
  • the reflection methods that return arrays were, in Eric's view, a mistake
  • array covariance was and remains an oddity; at least in C# 4.0 / .NET 4.0 this is done correctly for IEnumerable[<T>]
  • ApplicationException rather fell out of favor - was that a mistake?
  • synchronized collections - a nice idea, but not necessarily useful in reality: you usually need to synchronize multiple operations (Contains, then Add), so a collection that synchronizes distinct operations isn't all that useful
  • more use could have been made of the using/lock pattern - perhaps allowing them to share a re-usable (extensible?) syntax; you can simulate this by returning IDisposable and using using, but it could have been clearer
  • iterator blocks : no simple way of checking arguments ahead-of-time (rather than lazily). Sure, you can write two chained methods, but that is ugly
  • simpler immutability would be nice; C# 4.0 helps a bit, but not quite enough
  • no "this ref-type parameter cannot be null" support - although contracts (in 4.0) help with this somewhat. But syntax like Foo(SqlConnection! connection) (that injects a null-check / throw) would be nice (contrast to int? etc)
  • lack of support of operators and non-default constructors with generics; C# 4.0 solves this a bit with dynamic, or you can enable it like this


  • the iterator variable being declared outside the while in the foreach expansion, meaning that anon-methods/lambdas capture the single variable, rather than one per iteration (painful with threading/async/etc)
Marc Gravell
IEnumerable != IEnumerable<object> is indeed odd
Rauhotz
Well, the IEnumerable thing is a 1.1 hangover; you can use .Cast<object>() with LINQ, at least
Marc Gravell
The BCL folks said that `ApplicationException` was a mistake - not useful like they hoped. They also said that `System.Exception` should have been `abstract`.
Jay Bazuzi
Non-nullable: It should be a compile error to pass a regular reference type T to a something that takes a non-nullable T! (just like you can't pass int? to int). Passing the other direction is fine, of course.
Jay Bazuzi
ApplicationException: its way too tempting to use an existing exception in the framework that exactly describes an error in your application, it just feels too much like duplication to create new one derived from ApplicationException.
AnthonyWJones
@AnthonyWJones - indeed. And if it exactly describes the error, what purpose would it serve? Upstream code would then have to catch the system's FooException, app-a's FooException and app-b's FooException with no continuity.
Marc Gravell
FWIW, what Eric Lippert wrote in the blog post you cited is total bullshit. There's nothing wrong with returning arrays. Arrays can be immutable or resizeable. Arrays are often ideal for parallelism and purely functional data structures suck for parallelism.The real design flaw behind the issue he raised is that .NET screwed the pooch when it came to data structures.
Jon Harrop
+2  A: 

The .Parameters.Add() method on the SqlCommand in V1 of the framework was horribly designed -- one of the overloads would basically not work if you passed in a parameter with a value (int) of 0 -- this led to them creating the .Parameters.AddWithValue() method on the SqlCommand class.

Dave Markle
I agree, but I think you mean the SqlCommand.Parameters.Add() method.
Matt Peterson
+1  A: 
  • Be able to invoke an extension method on null variable is arguable e.g.

    object a=null; a.MyExtMethod(); // this is callable, assume somewhere it has defined MyExtMethod

    It could be handy but it is ambiguous on null reference exception topics.

  • One naming 'flaw'. 'C' of "configuration" in System.configuration.dll should be capitalized.

  • Exception handling. Exception should be forcibly caught or thrown like in Java, the compiler should check it at compilation time. Users should not rely on comments for exceptions info within the target invocation.

codemeit
Very handy, though - I have a "ThrowIfNull` extension method for parameter checking ;-p
Marc Gravell
you can do this? ugh ThrowIfNull it is interesting extension but this just seems wrong.
JoshBerke
In plain CLR you can Invoke instance methods on null references and if the method doesn't access the object or it's fields then the call doesn't throw null reference exception. (You can't do this in C# as it uses callvirt even for non virtual methods)
Pop Catalin
I ranted a bit about that exact thing over at http://blog.freakcode.com/2008/09/hazards-of-extension-methods.html
Markus Olsson
You can pass null values to static methods, for which extension methods are just syntactic sugar. Your change would alter semantics, especially for interoperability in languages without extension method support.
Bryan Watts
Yeah, agree and it is very handy.
codemeit
the exception thing is dead wrong. You can't fail fast if you HAVE to catch every goddamn exception that might be thrown in the call stack. But I DO wish it were much easier to identify any and all exceptions that might be thrown in a particular call and its resulting callstack...
Will
@WillI agree whole heartedly, checked exceptions just make developers add "throws Exception" more often than not. And in most real cases it causes more ambiguity than without it.
Guvante
A: 

Implicitly Typed variables were implemented poorly IMO. I know you should really only use them when working with Linq expressions, but it's annoying that you can't declare them outside of local scope.

From MSDN:

  • var can only be used when a local variable is declared and initialized in the same statement; the variable cannot be initialized to null, or to a method group or an anonymous function.
  • var cannot be used on fields at class scope.
  • Variables declared by using var cannot be used in the initialization expression. In other words, this expression is legal: int i = (i = 20); but this expression produces a compile-time error: var i = (i = 20);
  • Multiple implicitly-typed variables cannot be initialized in the same statement.
  • If a type named var is in scope, then the var keyword will resolve to that type name and will not be treated as part of an implicitly typed local variable declaration.

The reason I think it's a poor implementation is that they call it var, but it's a long way from being a variant. It's really just shorthand syntax for not having to type the fully class name (except when used with Linq)

lomaxx
you mean anonymous types?
Pop Catalin
Definitely anon types (new {...}), not implicitly typed (var)
Marc Gravell
Just re-read what I posted and it was wrong. I did mean implicitly typed variables tho
lomaxx
Eric Lippert explained why var cannot be used outside of methods, it is basically because it creates a black box of possibilities.http://blogs.msdn.com/ericlippert/archive/2009/01/26/why-no-var-on-fields.aspx
Guvante
var is not intended to be variant! it is precisely for the shorthand (especially anon types). enjoy dynamic when it comes along...
ShuggyCoUk
+10  A: 

I don't know that I'd go as far as to say it's a design flaw, but it would be really nice if you could infer a lambda expression in the same way you can in VB:

VB:

Dim a = Function(x) x * (x - 1)

C#

It would be nice if could do this:

var a = x => x * (x - 1);

Instead of having to do this:

Func<int, int> a = x => x * (x - 1);

I realise it's not much longer, but in Code Golf every character counts damnit! Don't they take that into account when they design these programming languages? :)

BenAlabaster
Microsoft should take Code Golf into consideration when it designs languages?
jrcs3
MS should take VB code into consideration when it designs C# - there's quite a few 'nice features' in VB that are missing from C#!
gbjbaanb
WTF is Code-golf? Taking a laptop along with your 6-iron?
Cyril Gupta
@gbjbaanb: The problem is with their logic that "C# programmers wouldn't want those VB features because it's not like anything they've wanted historically". So they kept all the nice features back for the non-purist VB programmers :P
BenAlabaster
@Cyril: It's the fine art of completing tasks usually in the fewest lines, fewest characters or most elegant code possible
BenAlabaster
Code golf as design consideration. Priceless :)
Learning
Is this a joke? How would the compiler know you meant Func<int, int> instead of, for example, Func<double, double>?
Ray Burns
@Ray Burns: How does it know in VB? VB supports it, so what's the difference?
BenAlabaster
@RayBurns Are you serious? Ever heard of type inference? Or is that too useful for you? (Geeze, I've been using that since 1989. You living in the dark ages or something?)
RD1
+17  A: 

I don't understand that you can't do

where T : new(U)

So you declare that generic type T has a non-default constructor.

edit:

I want to do this:

public class A 
{
    public A(string text) 
    {

    }
}


public class Gen<T> where T : new(string text) 
{

}
tuinstoel
A generic type declares how you will use objects of that type, i.e. their interface. The constructor is an implementation detail of that interface, which is not the concern of the consumer. When you need to create a parameterized instance, use a factory.
Bryan Watts
For info, although it can't do compile-time checking, there is some code in MiscUtil for using non-default constructors (in generics) efficiently, i.e. without Activator.CreateInstance or reflection.
Marc Gravell
Because it makes no sense and is confusing on some uses. Nonetheless it can be useful when working with immutable objects.
Pop Catalin
This just gave me an idea... You could probably accomplish this by using the new Code Contracts feature of C# 4.0. Just add that constraint into your constructor.
davogones
In general, lack of member constraints is annoying, yes.
MichaelGG
amen, I've always wanted this
Steve
+14  A: 
  1. I'm not a big fan of the Stream, StringWriter, StringReader, TextReader, TextWriter classes...it's just not intuitive what is what.
  2. IEnumerable.Reset throwing an exception for iterators. I have some third party components which always call reset when databound, requires me to cast to a list first to use these.
  3. Xml Serializer should have serialized IDictionary elements
  4. I totally forgot about the HttpWebRequest & FTP API what a pain in my....(thanks for the comment Nicholas to remind me of this:-)

Edit
5. Another annoyance of mine is how System.Reflection.BindingFlags, has different uses depending on the method your using. In FindFields for example what does CreateInstance or SetField mean? This is a case where they have overloaded the meaning behind this enumeration which is confusing.

JoshBerke
+1 I have to look up any of the XmlTextWriter, TextWriter, etc classes every single time. Same with the HttpWebRequest/Response stuff. Completely unintuitive API there.
Nicholas Piasecki
+1-1=0: XmlTextWriter etc, I agree its impossible to truely infer what they are from the name. HttpWebRequest I don't agree I find it quite intuative.
AnthonyWJones
To each his own I suppose. I guess with FTP I'd expect a higher level abstraction then what they have.
JoshBerke
+31  A: 

A small C# pet peev - constructors use the C++/Java syntax of having the constructor be the same name as the class.

New() or ctor() would have been much nicer.

And sure, tools such as coderush make this less of an issue for renaming classes, but from a readability POV, New() provides great clarity.

Scott Weinstein
Erm, how would it know what you're trying to create a new instance of?
BlueRaja - Danny Pflughoeft
@BlueRaja: Scott is referring to the naming of constructors in classes. `class Foo { new(int j) {i = j} int i; }`
dalle
+7  A: 

Some classes implement interfaces but they don't implement many of the methods of that interface, for example Array implements IList but 4 out of 9 methods throw NotSupportedException http://msdn.microsoft.com/en-us/library/system.array_members.aspx

ggf31416
+10  A: 
Jay Bazuzi
Well, this is a fine balancing act between re-use and locality. Often, it will turn out that something *can* be sensibly re-used, which isn't clear if it was nested in something else. Many things like iterators *are* nested, but perhaps more could be.
Marc Gravell
Just install ReSharper - with it's Pascal-case IntelliSense completion you could type "FB" and it will have the type FooBar in the list; even "FoB" will work. It's an incredibly useful bit of functionality to speed up the completion.
Greg Beech
I disagree. If you want that, make a Namespace Foo and then add in the classes, zoo, bar, and baz.
RCIX
Or put them as actual nested classes. That works too (i think)!
RCIX
I've worked with classes organized into very tiny namespace hierarchies, and its not a very fun experience, especially when you have a bajillion using statements at the top of ever file. Flatter namespaces are easier to navigate.
Juliet
The namespacing of types in .NET are good enough, except that many types in System belong elsewhere. I just wish for nesting of types where it makes sense.
Jay Bazuzi
+4  A: 

Static members and nested types in interfaces.

This is particularly useful when an interface member has a parameter of a type that is specific to the interface (e.g. an enum). It would be nice to nest the enum type in the interface type.

Jay Bazuzi
Isn' this very similar to your other suggestion?
RCIX
No, this one is about the C# language and the other is about the framework. Not everyone cares about the distinction, so let me say that this one is about what is allowed, and the other is about what is provided.
Jay Bazuzi
+11  A: 

We know so much about the right OO techniques. Decoupling, programming by contract, avoiding improper inheritance, appropriate use of exceptions, open/closed principal, Liskov substitutability, and so on. Any yet, the .Net frameworks do not employ best practices.

To me the single biggest flaw in the design of .Net is not standing on the shoulders of giants; promoting less than ideal programming paradigms to the masses of programmers that use their frameworks.

If MS paid attention to this, the software engineering world could have made great leaps in terms of quality, stability and scalability in this decade, but alas, it seems to be regressing.

Daniel Paull
+1 for the on-target rant; i would add to this the inability to subclass every class, the lack of interfaces for fundamental classes, and the reluctance to fix framework bugs even after several years
Steven A. Lowe
If we cut to the chase, are we saying that the .Net frameworks are just so bad that it's hard to settle on just which flaw is the worst? I do feel better after a vent and appreciate the upvote as I was expecting to be shouted down by MS fan boys.
Daniel Paull
I haven't voted either way, and anyway I'm very reluctant to issue down-votes, but I'm trying to figure out why I JUST DON'T CARE.
Mike Dunlavey
I think you're saying "it's not as good as it could be" which is a non-answer. Nothing is perfect. Provide specifics.
jcollum
No, I'm saying that there are numerous instances where the design is obviously flawed, then when you think they get it right, they still get it wrong. For example, my post to MSDN forums here: http://social.msdn.microsoft.com/forums/en-US/wpf/thread/f677b026-0719-47d7-a0b7-a0874df2ba17/
Daniel Paull
+, even though I'm a fanboy.
Will
@Will: you are a gentleman and a scholar.
Daniel Paull
+2  A: 

Microsoft won't fix obvious bugs in the framework and won't provide hooks so end users can fix them.

Also, there is no way to binary-patch .NET executables at runtime and no way to specify private versions of .NET framework libraries without binary patching the native libraries (to intercept the load call), and ILDASM is not redistributable so I cannot automate the patch anyway.

Joshua
What obvious framework bugs do you mean?
Robert Rossney
#1 Click on a partially visible child control of a scrollable control. The control is shifted into view before it receives the MouseDown event, causing the click to be somewhere else on the control than expected. It's worse on tree views, where it triggers a drag operation as well.
Joshua
#2 [this](http://stackoverflow.com/questions/241134/what-is-the-worst-c-net-gotcha/2595746#2595746) #3 [this](http://stackoverflow.com/questions/241134/what-is-the-worst-c-net-gotcha/2731387#2731387) #4 [this](http://stackoverflow.com/questions/241134/what-is-the-worst-c-net-gotcha/1404987#1404987)
BlueRaja - Danny Pflughoeft
A: 

I honestly have to say that during my years of .NET ( C# ) programming I haven't flaws in the framework design that I've remembered; Meaning that in my case there are probably no flaws that are worth remembering.

However, there is something that I dissliked a couple of years back when Microsoft was releasing XNA, they completely cut of their MDX 2.0-version, which made my games unplayable and not easy to just convert. This is a broader flaw and has nothing to do with the .NET-framework.

The .NET-framework actually follows a lot of Very Good design guidelines developed by a lot of the high end language architectures. So I have to say that im happy about .NET.

But to tell you something that could be better, I'd have to complain about the Generic system, I don't find the Generics for Interfaces such as "where T is MyObj" ( that's not the completely correct syntax. However, this part could have been made much better and clearer.

Imagine having an Interface which 2 different classes are sharing, if you want a Generic method inside that interface, you need to go over some nasty Generics-sytanx. It might just be me wanting to do weird stuff. Only memmorable thing for me though.

Filip Ekberg
+3  A: 

The way we use properties irritates me sometimes. I like to think of them as the equivalent of Java's getFoo() and setFoo() methods. But they are not.

If the Property Usage Guidelines.aspx) state that properties should be able to be set in any order so serialization can work, then they're useless for setter-time validation. If you come from a background where you like to prevent an object from allowing itself to ever get into an invalid state, then properties aren't your solution. Sometimes I fail to see just how they are better than public members, since we're so limited in what kinds of things we're supposed to do in properties.

To that end, I've always kind of wished (this is mostly thinking out loud here, I just kind of wish I could do something like this) that I could extend the property syntax somehow. Imagine something like this:


private string password;

public string Password
{
    // Called when being set by a deserializer or a persistence
    // framework
    deserialize
    {
       // I could put some backward-compat hacks in here. Like
       // weak passwords are grandfathered in without blowing up
       this.password = value;
    }
    get
    {
       if (Thread.CurrentPrincipal.IsInRole("Administrator"))
       {
           return this.password;
       }
       else
       {
           throw new PermissionException();
       }
    }
    set
    {
       if (MeetsPasswordRequirements(value))
       {
           throw new BlahException();
       }
       this.password = value;
    }
    serialize
    {
        return this.password;
    }
}

I'm not sure if that's useful or what it accessing those would look like. But I just wish that I could do more with properties and really treat them like get and set methods.

Nicholas Piasecki
I believe they provide the ISerializable interface and implicit constructor to do things like that, aka when you don't want the serializer to just call the properties.While a bit more work, it looks like you are already doing most of that work with your method.
Guvante
+4  A: 

0 moonlighting as enum

peculiarities of enum: http://blogs.msdn.com/abhinaba/archive/2007/01/09/more-peculiarites-of-enum.aspx

as illustrated by this good example: http://plus.kaist.ac.kr/~shoh/postgresql/Npgsql/apidocs/Npgsql.NpgsqlParameterCollection.Add_overload_3.html

my suggestion, put the "@" sign to good use:

instead of:

if ((myVar & MyEnumName.ColorRed) != 0)

use this:

if ((myVar & MyEnumName.ColorRed) != @0)

Michael Buen
+1 enum is one of the few things Java did right while C# didn't
BlueRaja - Danny Pflughoeft
+18  A: 

I'm really surprised that I'm the first to mention this one:

ADO.NET typed data sets don't expose nullable columns as properties of nullable types. You should be able to write this:

int? i = myRec.Field;
myRec.Field = null;

Instead, you have to write this, which is just stupid:

int? i = (int?)myRec.IsFieldNull() ? (int?)null : myRec.Field;
myRec.SetFieldNull();

This was annoying in .NET 2.0, and it's even more annoying now that you have to use jiggery-pokery like the above in your nice neat LINQ queries.

It's also annoying that the generated Add<TableName>Row method is similarly insensible to the notion of nullable types. All the more so since the generated TableAdapter methods aren't.

There's not a lot in .NET that makes me feel like the dev team said "Okay, boys, we're close enough - ship it!" But this sure does.

Robert Rossney
I wholeheartedly agree! This bugs me every time I have to use it (which is often). Argh! +1
Eyvind
The least they could do would be to come up with a new DataSetV2 class (bad name - just for argument's sake), that used nullable value types instead of DBNull throughout.
Christian Hayter
+5  A: 

Extension methods are nice but they're an ugly way to solve problems that could have been solved cleaner with real mixins (look at ruby to see what I'm talking about), on the subject of mixins. A really nice way to add them to the language would have been to allow generics to be used for inheritance. This allows you to extend existing classes in a nice object oriented way:

public class MyMixin<T> : T
{
    // etc...
}

this can be used like this to extend a string for example:

var newMixin = new MyMixin<string>();

It's far more powerful than extension methods because it allows you to override methods, for example to wrap them allowing AOP-like functionality inside the language.

Sorry for the rant :-)

Mendelt
Interesting, but i prefer extension methods. If i get a library that contains a bunch of extension methods for strings, i don't want to have to change all of the string references to MyMixin<string> in order to get the new stuff. It's kind of minor, sure, but that transparent addition of methods is what makes extension methods so nice.
RCIX
BTW did you know that that works already?
RCIX
I don't see how LINQ could work this way
BlueRaja - Danny Pflughoeft
+3  A: 
  1. The System.Object class:

    • Equals and GetHashCode - not all classes are comparable or hashable, should be moved to an interface. IEquatable or IComparable (or similar) comes to mind.

    • ToString - not all classes can be converted to a string, should be moved to an interface. IFormattable (or similar) comes to mind.

  2. The ICollection.SyncRoot property:

    • Promotes poor design, an external lock is almost always more useful.
  3. Generics should have been there from the beginning:

    • The System.Collections namespace contains a lot of more or less obsolete classes and interfaces.
dalle
As for ToString(), it is called by the debugger for all objects so it had to be in System.Object anyway.
Joshua
So ToString() should exist because of the debugger? The debugger doesn't need ToString(), it could use IFormattable or just output ClassName 0xaddress if the object doesn't implement IFormattable.
dalle
1. Those methods are so common it was decided that the oddball cases were ok, does it matter if someone can call Object.Equals on your class? It is known that there may or may not be an implementation, and requiring : IEquatable, IFormattable on 99% of classes is odd.
Guvante
2. How does an external lock differ from SyncRoot? If you are arguing against the naked lock() statement you are right there are many better alternatives, but it gets the job done.3. Good point
Guvante
I agree with Guvante: the general rule is **always make the common case the default**, and classes in which `.ToString()`/`.Equals()` are useful is by far the common case.
BlueRaja - Danny Pflughoeft
+35  A: 

TextWriter is a base class of StreamWriter. wtf?

That always confuses the hell out of me.

Quibblesome
+1 I have to look it up every time. (Whaddaya *mean* I can't new TextWriter()?)
Nicholas Piasecki
+6  A: 

One of the things that irritates me is the Predicate<T> != Func<T, bool> paradox. They're both delegates of type T -> bool and yet they're not assignment compatible.

Greg Beech
There is a trick using Delegate.Create and some casting to do the conversion, but at least being able to do an explicit cast would be nice (I can understand the lack of support for implicit however)
Guvante
+2  A: 

One thing that ticked me off in 1.x was when using the System.Xml.XmlValidatingReader, the ValidationEventHandler's ValidationEventArgs doesn't expose the underlying XmlSchemaException (marked internal) which has all the useful info like linenumber and position. Instead you're expected to parse this out of the Message string property or use reflection to dig it out. Not so good when you want to return a more sanitised error to the end user.

Kev
A: 

The CLR (and therefore C#) doesn't support Multiple Inheritance and ASP.NET is stuffed with LSP breaks...

Those are my "favorites"...

I could probably find more bugs, but those are the ones I dislikes the most...!! :(

Thomas Hansen
Multiple Inheritance is handled 99.9% of the time by interfaces, and 99% of uses of it in languages that support it are clunky and confusing.
Guvante
@Guvante - I agree. Multiple inheritance rarely makes code simpler or easier to understand and maintain. (Indeed, single inheritance is only rarely a good idea, and increasingly people seem to be recognizing that there are better ways of reusing code.)
RD1
@Guvante: I would say it's handled 95% of the time with interfaces. However, with interfaces **and** extension methods, it's handled 100% of the time. Hurray!
BlueRaja - Danny Pflughoeft
+3  A: 

To add to the long list of good points made by others already:

  • DateTime.Now == DateTime.Now in most, but not all cases.

  • String which is immutable has a bunch of options for construction and manipulation, but StringBuilder (which is mutable) doesn't.

  • Monitor.Enter and Monitor.Exit should have been instance methods, so instead of newing a specific object for locking, you could new a Monitor and lock on that.

  • Destructors should never have been named destructors. The ECMA spec calls them finalizers, which is much less confusing for the C++ crowd, but the language specification still refers to them as destructors.

Brian Rasmussen
The `DateTime.Now` one is the world's most obvious race-condition, but +1 for the rest
BlueRaja - Danny Pflughoeft
It is not so much that it is a race condition, but the fact that they made it a property. Properties look exactly like fields, so it is rather surprising behavior IMO.
Brian Rasmussen
+9  A: 

I don't like the C# switch statement.

I would like something like this

switch (a) {
  1    : do_something;
  2    : do_something_else;
  3,4  : do_something_different;
  else : do_something_weird; 
}

So no more breaks (easy to forget) and the possibility to comma-separate different values.

tuinstoel
Actually I think it would be even better if it would require either a single statement or a block in curly brackets - like everything else in C#. Without the ability to fall through, the current break syntax is a bit dodgy and it doesn't limit to scope either. (AFAIK, it might, I don't know)
DrJokepu
I don't understand what you mean. Post your own 'ideal' switch statement here. I don't want fall through but comma separated values.
tuinstoel
DrJokepu: fall-through exists, even for non-empty clauses. You only have to make it explicit, by using `goto case`.
Konrad Rudolph
By the way, I agree with OP. `switch` is fundamentally broken in all languages that emulate C's deliberatly crippled version (optimized for speed!). VB fares much better, but is still light-years behind languages with pattern matching (Haskell, F# …).
Konrad Rudolph
Konrad: You're right about goto of course - and probably that's the reason of still using the C switch syntax in C#
DrJokepu
tuinostel: something like switch (a) { case 1 { do_something; } case 2 { do_something_else; } } - that is, getting rid of the break statement *and* requiring proper code blocks for each case
DrJokepu
Having break seems like a mistake in general, isn't it a compile error to emit it? It seems to only be there to ease the transition from C to C# (aka teaching devs that they can't auto fall through)
Guvante
Here here! Make the common case the default!
BlueRaja - Danny Pflughoeft
+5  A: 

Events in C#, where you have to explicit check for listeners. Wasn't that the point with events, to broadcast to whoever happen to be there? Even if there aren't any?

Thomas Eyde
It is annoying that there is not sugar for this when you want it, I see why they do it tough, it encourages not instantiating the event's arguments if not needed
ShuggyCoUk
Hm. I either don't understand or disagree, or both :-). I can't say I ever felt discouraged to instantiate anything. This smells like premature optimization to me.
Thomas Eyde
Partial methods are a viable alternative, in some cases.
Robert Harvey
PLUS all the coupling this causes... MS has CAB which fixes both of these problems, but CAB has many problems of its own due to limitations in C# (eg. strings rather than enums as event-topics)- **why not just make loosely-coupled events part of the language**!?
BlueRaja - Danny Pflughoeft
+4  A: 

The awful (and quite invisible to most people) O(N^2) behaviour of nested/recursive iterators.

I'm quite gutted that they know about it, know how to fix it but it is not viewed as having sufficient priority to merit inclusion.

I work with tree like structures all the time and have to correct otherwise smart people's code when they inadvertently introduce highly expensive operations in this way.

The beauty of "yield foreach' is that the simpler, easier syntax encourages correct, performant code. This is the "pit of success" that I think they should aspire to before adding new features for long term success of the platform.

ShuggyCoUk
This is especially flawed, because it goes against intuitive expectations of O behavior ans so will trap many people
oefe
+5  A: 

Don't like it that you can't use the values of one enum in another enum, for example:

    enum Colors { white, blue, green, red, black, yellow }

    enum SpecialColors { Colors.blue, Colors.red, Colors.Yellow }
tuinstoel
+4  A: 

The terribly dangerous default nature of events. The fact that you can call an event and be in an inconsistent state due to subscribers being removed is just horrible. See Jon Skeet's and Eric Lippert's excellent articles for more reading on the subject.

jasonh
+13  A: 
naasking
+3  A: 
  • null everywhere.

  • const nowhere.

  • APIs are inconsistent, e.g. mutating an array returns void but appending to a StringBuffer returns the same mutable StringBuffer.

  • Collection interfaces are incompatible with immutable data structures, e.g. Add in System.Collections.Generic.IList<_> cannot return a result.

  • No structural typing so you write System.Windows.Media.Effects.SamplingMode.Bilinear instead of just Bilinear.

  • Mutable IEnumerator interface implemented by classes when it should be an immutable struct.

  • Equality and comparison are a mess: you've got System.IComparable and Equals but then you've also got System.IComparable<_>, System.IEquatable, System.Collections.IComparer, System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.Collections.Generic.IComparer and System.Collections.Generic.IEqualityComparer.

  • Tuples should be structs but structs unnecessarily inhibit tail call elimination so one of the most common and fundamental data types will allocate unnecessarily and destroy scalable parallelism.

Jon Harrop