What do you consider a bug in C#, or .NET framework that Microsoft will not fix, or hasn't fixed yet?
I'm hoping the answers to this question will give us better patterns to work from, and build more robust code.
|
What do you consider a bug in C#, or .NET framework that Microsoft will not fix, or hasn't fixed yet? I'm hoping the answers to this question will give us better patterns to work from, and build more robust code. |
||||
|
|
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or specific expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, see the FAQ for guidance.
|
That you have to check if an event if null before raising it
If listeners are connected, then the event contains a list of listeners, if no listener is connected, it is null (instead of just an empty list). This behavior has existed since .NET 1.0, and to me highly illogical. |
|||||||||||||||||||||
|
|
All references are nullable by default Anders Hejlsberg who is considerd the "father of C#" even said this was a mistake in a Computerworld interview:
|
||||
|
|
|
Out of range ints as enums. You can cast an out-of-range enum from an int and the compiler is fine with it:
See here for a longer discussion (and some replies). |
|||||||||||||||||
|
|
The requirement for
Won't work (compile error). You have to
Mysteriously, however, this works:
If you try to put the |
|||||||||||||||||||||
|
|
Closures It may not look like it but the following code will print 10 on every line...
Fixed version:
To learn why this is, check out this article by John Skeet |
|||||||||||||||||||||
|
|
This is going to be controversial :) Garbage Collection Now, I've been involved with this since Java first came out (I went to a "w00t" presentation about Java at Hursley Park many years ago where a chap told us all how wonderful it was, and mentioned GC. Did you know Java initially didn't even have finalisers? Crazy, everyone at that meeting told the presenters just what a stupid idea Java was because of that). And Microsoft decided that a GC was the way to go with .NET, but although they had finalisers they didn't really like it when a quite vocal group of us on the Microsoft forums told them a lack of deterministic finalisation was a mistake. They added the IDispose as a pattern shortly afterwards, and the using keyword a few years later. The moral of the above stories is that 2 developers of new languages just didn't quite get it. They added a great cool feature where you no longer had to worry about alloc/free of memory manually, the language feature would take care of it for you and you no longer had to worry our pretty little heads about it. Only the problem is that they forgot something. Garbage collection is great for memory management. It is useless at object management. Most applications revolve around object lifetimes, they don't really care to much about memory except as a 'container' to hold your objects. So having GC that frees up your memory isn't going to cut it, except in those cases where your object is simple and contains nothing more than memory anyway (which, ok, is 90% of all objects - but who cares about the simple stuff when you have complex stuff to build). So because of this, we have the situation where we not only have various features added to the language to attempt to make up for the deficiencies, but we also have to manually manage the object lifetimes as well! In a RAII-based language, object lifetimes are easily managed. In a GC one, we have to not only implement special IDispose methods (in addition to the finaliser, and make sure they do not conflict with issues like double-deletion, etc), and 'smart pointer' classes like SafeHandle, but we also have to manually put using statements in to ensure they are called, and remember to write your exception handling code correctly so your objects won't leak. You also have to understand what the internals of your libraries are doing, or you end up with leaks such as those when not manually un-associating event handlers on a GUI. How wonderful this 'automatic', 'no worries' memory management mechanism is! So, remember that GC is great for memory, bad for objects, and the problem is that the language designers didn't make a distinction between the two equating objects == memory. The fix is of course to split the distinction. Imagine if objects were treated separately, with full automatic scoping using smart pointers. The memory underlying the object can still be allocated and freed using the GC, but the destructor (I hesitate to use either finalise or dispose as they're both band-aids) can then be implemented in a RAII fashion. Thus you'd get the best of both worlds - fast, no-leak memory, and deterministic object finalisation. |
|||||||||||||
|
|
Allowing any object to be used as a lock You can synclock on any object. I'm not really sure why this is the case. Maybe the ease of writing 'synclock (this)'? There are several consequences of this decision:
Personally, I would have gone with a specialized lock class. If you want to hold a lock, you use an instance of the special class. This has the nice effect of hiding locks by default and naturally allowing for different types of locks (read/write, up-to-n, non-re-entrant, etc). |
|||||||||
|
|
I would consider cold-loading times so bad that it's a bug. This is what is holding .Net back from being a first class environment for client apps. For instance, consider that on a freshly booted machine, it will often take upwards of 5 seconds to launch a simple WPF app that doesn't display anything but a blank window. In what other environment do people put up with this? Java has the same problem, that too is primarily a server framework because of this. This problem reduces .Net on the client to being confined to in-house enterprise development (where users don't really have any choice). No one in their right mind would develop client apps for the masses in this environment. |
|||||||||||||||||||||
|
|
Using() may cause object initializers to leak if an exception is thrown If an exception is thrown within a For a detailed explanation of this see this article. Many people have considered this to be a bug, however this is by design. Eric Lippert's response:
Based on that answer I'm considering using the |
|||||||||||||||||
|
|
I don't think everyone will agree but I would say their entire Ajax implementation and more specifically the UpdatePanel. The fact that the entire page renders and gets sent back to the browser and then just a small piece of it is used completely undermines the entire concept of Ajax and just going back to the server to get what you need. Seems very hacky to me. I am aware there are other implementations but for the Microsoft one to be so inefficient I would consider that a bug. |
|||||||||||||
|
InternalsVisibleToAttributeThis attribute allows one assembly to be able to see internal methods, properties, and members of another assembly. This is just plain poor development practice. Though I do not know for sure why it exists, I believe they introduced it along with their own unit test framework in order to let unit tests be able to access internals in the classes that they test. This is obviously the wrong way to write tests, as tests should test the public interface of a class. And it is hard to explain to coworkers that are not that experienced with unit tests that I am right, and MS is wrong. |
|||||||||||||||||||||
|
|
What has bugged me lots of times already is that the XmlReader doesn't expose the stream position of a given tag, although it has that information internally. For example I have a N GB XML stream and I need to separate a header with meta information from an inner document with the content (a quite common scenario for example in BizTalk). To do that stream based (a must when processing multiple big documents) with .NET you have to implement something close to a full blown XML parser which then does expose the stream position. And that's not the way it should be. |
||||
|
|
|
The fact you can't properly load a control by classname/assembly kills me every time. And it still hasn't been fixed: |
||||
|
|
|
Interating through a null collection with foreach throws an error. IMHO, it should just continue on. Yes I understand that it's null, but it's just annoying as annoying can be, and a real gotcha for newbies. |
|||||||||||||
|
|
The TotalHours of a Timespan doesn't correctly show above 24hours without using Math.Truncate. Although this is not a bug its weird functionality I believe. Has caught me out a few times when I was learning. Edit: Example: http://stackoverflow.com/questions/3505230/format-timespan-greater-than-24-hour |
|||||
|
|
|
||||
|
|