seems to have sparked some feedback, and judging by the response on dzone, it does rather tend overwhelmingly to the negative.
This is of course what you get when you chuck opinions about on such a touchy subject.
However since I am a Java guy trapped in a .Net job I can add some more fat to fire :-)
To me .Net and specifically C# is a missed opportunity and from my point of view it got a lot of things wrong.Structs and specifically Structs for "primitive" types. It's great to be to be able to do 1.ToString() but after a while you hit the limitations of this which you wouldn't have had if they were objects, there are some workarounds like the ? (nullable) operator, but to me this is a hack. Would it have hurt to make these proper objects?Delegates. I still think that - despite their aesthetic ugliness and stupid final requirement - Anonymous classes are better conceptually. But after all that Bill Joy was right, closures are the way to go. M$ had the opportunity to show tremendous leadership here, they didn't, and now C# is playing catchup to [insert favourite dynamic language].Properties. From an OO purist point of view these are bad anyway. Having said that with UI frameworks it would be great to have some type safe binding using properties. But wait, you can't do that in C#. You still have to send in a string to for the property name.The fact that you are forced to explicitly define virtual methods, this coupled with the fact that you are forced to define interface methods in an abstract class.Partial classes. Great for generated code, but I can't wait to go hunt all the different fragments of this partial class with Visual Studio's rather anti-deluvian user interface.
Structs are there for performance as the structs can be allocated on the stack. You see a huge difference in heap vs. stack when dealing with a lot of data.
Delegates - I think their syntax is quite elegant and find their usage to help out in many situations. If you don't like them, what about anonymous methods over anonymous classes? Are the anonymous methods the feature C# is playing catchup to [insert favourite dynamic language]?
Properties - Not sure I get what you don't like about them, but they are just a way to expose a field w/ the ability to do some sort of validation on each get/set. IMO, this is much better than the Get(), Set(val) way and of course, properties are a major staple of UI and databinding, specially WPF.
Partial classes are good not only in code generation scenarios, but also is code organization. Developers can make a mess out of this, but like most code features, if used correctly can help a great deal.
I'm not sure about the having to define virtual methods and interfaces in abstract classes....But in .NET classes/abstract classes are seperated from the notion of an interface. An interface defines 0 code, only methods, properties and events. An abstract class is simply a class that can not be initiated and must be subclassed.
I enjoyed reading your blog posts and its nice to see someone like yourself giving an attempt at an unbias look into the "other side". I look forward to reading more!
Smalltalk, Python, Ruby and Scala use objects for primitives despite the performance hit. Furthermore you could have given the developer the option to force a pure primitive instead of an object (would you call unboxing :-))
Delegates are useful, but closures are vastly superior. Dynamic languages have popularised closure usage, C# only got them in 3.5.
Yes properties are used for WPF, but I still cannot bind to a property by passing a handle to the property such as a PropertyInfo object which is inserted by the compiler, I have to pass a string to the method name, not very type safe.
In Java all methods are virtual by default unless you declare them as final. Furthermore if you have an abstract class which implements an interface you are not forced to redefine those methods as abstract in the abstract class if you don't need to implement them.
Thanks a lot for the feedback, I shall try to keep the content as interesting as possible :-)
If you are looking for a high level of control w/ boxing/unboxing, you should use CLI/C++, which can compile to pure IL. I don't know if Ruby is a good example for performance and I'm ignorant to the characteristics of the other languages, but given the nature of the stack being faster (vs the heap) I'm not sure how a language can box/unbox w/o a performance hit. I do come from a C++ background, so I can't claim I know all the new compiler tricks these guys are using.
Closures (aka anonymous methods) actually have been in .NET for about ~4 years when .NET 2.0 came out. I don't find closures to be comparible to delegates, but compliment them as I can assign a closure to a delegate variable and pass/store the delegate along if need be.
I think I see what you are getting at with the properties. In WPF, its a little different as when you set a Binding in code, you supply the dependancy property, not just a string. Not exactly type safe, but a bit better. In the other frameworks, like ASP.NET, you do in fact supply a string for which property you are binding to. But even if you supplied a PropertyInfo instance, you would just get a type-check for the type of "PropertyInfo", not the actual type - as it is with WPF. I agree this would be a nice feature for the compiler to check, but the nature of databinding can be so "dynamic" that it may be worthless. The "dynamic" nature I speak of is even more in WPF with the use of ValueConverters.
I'm still a little confused about the beef with the abstract classes/interfaces. Perhaps a good post idea would be to compare the languages with code examples...On that note, I've just subscribed to your blog :)
Here is a link to a rant about the interfaces/abstract classes:
What I was getting at with the unboxing is that perhaps it might have been better to make them objects by default but allow the developer to force primitives if they need to do performance critical code. I admit though that I am taking this from a business systems developer point of view, where this type of flexibility is more relevant.
I agreed with you on the virtual methods until 24 hours ago. My justification is what if a class has been written by a muppet (95% of the time this muppet is me) and you need to override a method that isn't virtual. You have to contact the author of the class and get them to mark that method as virtual (95% of the time this is no problem, the other 5% you may as well give up).
I did a bunch of research yesterday while having an argument with a friend on this matter. These are the main reasons I found from this page, http://www.artima.com/intv/nonvirtual.html
The highlighted reasons are
1. Performance. Nonvirtual methods are faster than virtual methods. Many programmers, me included, forget to mark a method as final.
2. Versioning. When designing an API and you publish a virtual method you are promising that not only will this method do x and y, it will do it after a and before b. You should be aware of the implications before doing this.
Please read that web page for Anders' comments on versioning.
Hi Ox you make some very good points.
Just my own thoughts on this though.
- As a framework developer I can never know exactly how people are going to use my classes, I'm more worried about protecting code I specifically want protected.
- I have no problem for explicitly indicating intent to override an existing method with the override statement thereby indicating my intent to the compiler without needing to declare parent methods virtual. do you think would this be enough to prevent most of what Anders is worried about?
An implied side effect of what your saying is that the compiler will assume that a method that doesn't say override will be assumed to be new. e.g. public new void ToString();
Apart from the performance issue of having a method virtual there is this to consider.
If you mark a method as virtual, not only are you saying, go ahead, override this, but you are saying, in the next version of this library, you will still be able to override this in the same way. It is all about the outgoing promise you make when you set a method to virtual.
http://www.artima.com/intv/nonvirtual2.html will give you a better idea of what I mean.
On the performance issue, considering that invokeinterface is slower than invokevirtual, virtual method overhead are the least of my worries.
Is this why interface usage seems to be rather discouraged in .Net?
I did read the article but I feel that just using the override in a child class is sufficient since now you are telling the compiler that your class will adhere to the parent contract of the method, this too will pick up a change in version of the parent, this is how scala does it.
I hate .net and C# too.
I have many years experience in working on Micro$oft way and now i feel flying with java, believe me C# have not any chance in enterprise, mobile and now desktop.
Come on Reza...This was a pretty good discussion up until your comment.
I understand how one has their own opinions and favors a particular technology, but to deny the significance of .NET on the Desktop and in Enterprise is to be totally misinformed.
Java and .NET are both very strong at what they do..but no technology is a one-size-fits-all and neither are going anywhere anytime soon.
Structures are unnecessary though. Yes, they're used for performance because they allocate on the stack but the runtime could use escape analysis to determine if something can safely be allocated on the stack. In .NET stack allocation is static. In the JVM, stack allocation is dynamic.
I'm not sure what escape analysis is, but it surely sounds like more overhead, like boxing/unboxing.
In .NET, structs allow you to encapsulate data (for convenience) that can exist on the stack (for performance). Something you cannot do in Java.
Nullable types are also a huge plus. I'm sure if you ever worked with a database, an int field can be configured to be a value or a null...Why not have the same functionality within your language?
In a related topic, I don't like how Java does generics compared to .NET. It compiles everything to a list, meaning value types in a java generic collection all must be boxed/unboxed, whereas .NET compiler actually creates the generic type and no boxing/unboxing is needed.
Post a Comment