(NOTE: um, lucky for me I had a copy of most of this post in my clipboard, my session timed out before I hit submit and my post bounced, I hate web based systems. You guys wanna bump the session timeout a little?).
This is good feedback - could you give us specifics though please?
Sure. This is really quick (yeah, so quick my session timed out.. ), so forgive shortness, spelling mistakes, lack of explicit details, etc.
WinForms databinding sucks. It gobbles exceptions (very bad thing to do from my perspective, many apps are left in an indeterminate state once they throw), I can make it leak with little effort (i.e. while trying not to), and I'm pretty sure it just 'glues'
event listeners permanently to bound objects then manages a weak reference to same, although I'm not certain of this. DataSource is 'object'? Come on..
The WinForms validation patterns suck. Validate() returns a value and causes side-effects, it's anyone's guess where the input focus ends up, I can make this fail (again, while trying not to) such that an attempt is made to bind data that I invalidated.
Validation code is defined and runs in the user-interface? No problems if this is what I want to do, but I don't. I want full support for a decent MVC pattern 'ready to go' in WinForms, the closest I have is support for events, which causes me memory problems.
There are many bugs I've stumbled across in basic UI controls. Reading a value from a NumbericUpDown for example can cause a TextChanged event to fire by side-effect (or something like that, from memory, maybe the other way around). TabControls are nothing
but pain. Visual controls are all pretty basic (i.e. not very pretty, or consistent (e.g. compare a toolbar to a menu)). Visual inheritance 'barely' works and I 'lose' stuff specified in the designer all the time. Not to mention problems that I've had with
VS.NET while using the designer that caused it to leak to utilise over 1GB of RAM within half an hour (I suspect a Dispose/events problem?) requiring a restart. Each bug requires a 'work around' that I have to implement thoughout hundreds of thousands of lines
Lapsed-listeners crippled one of my apps because I had assumed that the .NET events implementation would 'magically' take care of unsubscribing events for me (as a part of garbage collection), how wrong I was. I've since discovered how primitive it really
is and have been prodding for easily 6 months and have not been able to get much guidance on how to handle this problem (feeling very much on my own). This is a serious 'memory management' issue for me, while MS claims issues like this are *gone* in managed
code? I asked about this on Channel9 the best part of two weeks ago but didn't get a response.
The Dispose() pattern is terribly specified. I really don't understand when and where I am not supposed to use it. I see it being 'butchered' by framework classes (on an enumerator to indicate 'completion' or 'logical disposal' in the C# 2 spec for example?
What's the go with the Disposed event on Component, will that always fire if Dispose is optional?). Some say Dispose is only for managing the timely release of unmanaged resources, others say it's for anything you want to use the 'using' keyword on, others
say it should be called if it has it, others say it is optional, there are traps with finalization, no-one really knows what a 'managed resource' is, etc. What is 'managed' about this? I can use this stuff, 'my own way', but these are system interfaces, surely
they should have rigid implementation contracts.
The IComparable interface doesn't specify how to treat ValueTypes. What of ValueTypes that represent a 'null value'? Why should Int16.CompareTo(123) throw an exception and not allow for an attempted conversion? There is little direction (or discussion) that
I could find. ValueType derives from System.Object but I can't assign it a null reference (I'm not saying I should be able to, just that this causes anomalies).
What's going on with Close vs Dispose? Was that a bad decision?
What of the difference between implementing an interface and exporting an interface? ControlCollection calls Dispose on the Control interface for example, but the doco claims (correctly I believe) that the IDisposable interface is to be called. I haven't
had any direction on the rules regarding 'reimplementing' interfaces on derived classes. The 'using' keyword on the other hand always calls on the IDisposable interface. Form.Dispose causes a change in state to ListView items it owns before calling ListView.Dispose(),
it sucked to find that out the hard way.. by myself. What is the go with tight-coupling like that?
I've seen strange conversion behaviour in the SqlTypes library ((SqlBinary)null for example, fair enough I guess..?), along with stuff like Xor() that defines treatment for null values, and contains 'set like' operations which I'm not sure are useful in
imperative code. There is no defined conversions for DBNull. There is no support for nullable types in the UI controls, etc.
I had serious problems trying to figure out how to bend the ASP.NET controls, etc. to my will. Ended up implementing my own HttpHandlers (which I thought were cool) in the end. The ViewState was a problem for me (not understanding how to exploit it, control
it, etc.) the graphical designers where far from helpful (I was way more productive when I stopped trying to do battle with them and just spat text at a stream) and trying to manage a WebForm 'as if it were a WinForm' just doesn't work for me (unless I'm writing
'throw away' code, which doesn't exist right?).
What of throwing exceptions from constructors and the potential for creating memory leaks since 'this' is addressable and can be externalised (trivially, by subscribing to an event) while in the constructor? There is no guidance on this. Where is the BOLD
PRINT explicitly stating that when I use '+=' I'm passing a reference to my class to another class that must be removed to avoid a leak?
I haven't found it easy to create 'localizable' apps. Admittedly, I haven't tried too hard. But then, who has the time? Where is this 'pit of success' you speak of?
I'm not super impressed with the exception management patterns. They're good, but their not great. I can throw a bare 'Exception' for example, or throw 'system exceptions'. I think more could have been done in this regard. I'm not sure that relying on polymorphism
was necessarily the way to go.. most code I see just uses 'throw new Exception("unlucky");', no requirement to propagate the inner exception, and so on.
I'm not sure that I love the support for serialization. What I played with for XML serialization was extremely limited, and relied too heavily on attributes for my liking (i.e. exclusively?). Deserializing with the (reflection based?) private constructor
on a class marked as [Serializable] is sloooooow. I think I'd have to write unverifiable (unsafe) code to speed this up, short of implementing my own serialization framework (non-trivial, graph problems, etc.).
Serialization with the SoapFormatter ties the serialization schema to the type version, I don't know how to avoid this easily.
Much of the doco sucks in general. For me the problem with doco tends to revolve around not enough rigid and correct detail. I know it's hard, so I don't want to come off as 'sledging' anyone. Sometimes the opposite problem exists, there is 'too much' information,
and I just can't allocate the time to consume it. Sorry, damned if you do, damned if you don't.
What the 'event' keyword actually does to your class was not at all intuitive. Nor were the +=, -= operators. Now that I know, I'm happy enough, but I'm not sure that I'm the majority on this issue (many of the devs I speak to have never thought about what
happens when they subscribe to an event).
I have a 'configuration' interface for reading app settings, but have to use an 'xml' interface for writing.
I've had to come up with my own tools and patterns for managing Object/Relational mapping and optimistic concurrency in a distributed environment. DataSets and DataBinding have been either 'not powerful enough', 'too buggy', or 'too difficult to implement
in complex scenarios' for me to use. I can get 80% of the way to where I need to go using these methods, the last 20% requires me to stop using these methods and DIY.
Managing boxing can be unintuitive. There is an 'out' and 'ref' keyword but no 'in' (or 'const') for passing structs to methods. Performance can be significantly improved by passing by ref but I can't communicate my intentions with the language (let alone
ensure they are enforced).
I've been on the receiving end of plenty of 'incorrect' advice over the years as we all plough forward trying to figure this stuff out (fire and forget thread leaks and Close vs Dispose spring to mind). And a part of me really doesn't like having to give
you guys feedback. On the one hand I'm your 'customer' and I'm telling you what I need, sure, but on the other hand I'm a software developer just like you who's spent countless hours figuring out what's wrong with your platforms then I spend time telling you
so that you can fix it then I part with thousands of dollars again next year so that I can buy it off you and figure it out again.. I'm not having delusions of grandeur, I'm just upset that I have to waste time trying to figure out how I'm supposed to use
the stuff your shipping, particularly when it seems like grassroots or 'first class concept' stuff, like 'events', 'resource management', 'exception management', 'system interfaces', etc. that you are supposed to have looked after for me, but that I feel are
too rough aroung the edges. To add insult to injury all anyone seems to want to talk about these days is Longhorn, Yukon, and Whidbey, or just make sweeping comments about how wonderful managed code is. I'm using .NET v1.1 on Win2k with IIS and SQL Server
2000 and I'll be deploying apps that are expected to run on those platforms for at least the next 3 years, I don't know how comfortable I am about that at the moment.
Many of the books I've read on .NET have been wrong, oversimplified, or misleading. As is much of the publicity that I see (compared to the reality that I see) and online material. The samples that I've looked at that ship with VS.NET are a joke (i.e. built
in memory leaks in the WinTalk sample for example (from memory)). This is not a mature technology, but all the info coming from MS is about how it is becoming obsolete..? Will you be calling my code 'legacy managed code' before I ship it? Whidbey may be a
mixed blessing, half of my code will likely become redundant with the introduction of generics, that might be good, but it kind of sux when I'm going to be writing more of it just after I send you this.
The ".NET" brand name _really_ ticks me off.
At least I'm fortunate enough to be deploying in a controlled environment. I've seen people asking about all sorts of stuff to do with deployment that was supposed to be simple, and apparently there are still plenty of systems that don't have (and won't
install) the framework.. problems with code access security, 'decompilability', etc.
Sorry for the disjointed nature of this post. I started at the top and typed everything that sprang to mind as fast as possible. My biggest problem is "how to manage memory in a managed environment", sure we don't 'malloc', but 'new Thing()' has the same
effect, with less explicit control (it's not like we're not using memory anymore). When I see DataBinding internals using 'WeakReference' I worry.. basically, I suffer from permanent information overload, and when I find bogus, unclear, incorrect, or buggy
doco or framework implementations that waste my time then I take one step closer to the point where I curl up into the fetal position and start sobbing. Help me damn it! It's not that I don't want to think hard about programming, it's just that I want to focus
on business problems knowing how my tools are going to help me, but my experience with .NET to date has been focusing on framework issues and how they are hindering me.
Perhaps I'm expecting too much from my tools, and not taking enough responsibility for myself? I reckon I'm pretty familiar with the framework, and I reckon I'm a decent developer, but I've been 'doing battle' with .NET for years, it has been very far from
'the light of my life', much closer to the 'bane of my existance'. I guess I'm spoiled in many ways too, it's much better than what MS has shipped in the past, and I understand that it's a mammoth effort, but when I drill down into the nitty gritty I generally
find the dirty laundry and know that so much more could be done or find that I can't get the direction that I need. Ooops, now I'm ranting aren't I..
Um, the C# syntax is nice.. (although VS.NET doesn't syntax highlight the add and remove keywords)