7 ms·
If I attempt to generalize it, I think most of C#'s differences in language design that have opposites in Java are superior. Examples include: + not virtual b
by jasode 10y ago
If I attempt to generalize it, I think most of C#'s differences in language design that have opposites in Java are superior. Examples include:
+ not virtual by default (so base classes can be changed more easily without breaking/recompiling downstream clients that the base class writer doesn't know about; specifying something as "virtual" should be a deliberate conscious decision by the class author)
+ value types (for speed, because J Gosling's idea that "_everything_ is an object is 'simpler' for programmers" has a cost -- the boxing & unboxing, and inefficient cache-unfriendly pointer-chasing containers)
+ no checked exceptions (checked exceptions have benefits in theory but real-world practice shows that it forces programmers to copy-paste mindless boilerplate to satisfy the checked-constraint)
+ unsigned types (very handy for P/Invoke API boundaries because legacy Win32 has unsigned params everywhere; yes, yes, Gosling said that unsigned types are confusing and dangerous but nevertheless, they are still very useful)
+ many other examples
This doesn't mean that Anders Hejlsberg's C# language team was smarter than J Gosling's Java team. They simply had 7 years to observe how Java programmers (mis)used the language and therefore, could correct some design mistakes.
Nevertheless, C# still made some dubious decisions such as renaming "finalizers" to "destructors". Java had the better name and C# should have kept the original terminology.
- namelezz 10y agoWhat do you think of partial classes and methods in term of code quality?
- jasode 10y agoI've always thought of "partial classes" as a language feature motivated by code generators not stomping on programmers' manually entered code. E.g. Winforms generates some declarations in one partial class while the programmer codes UI handlers in the other partial class.
- namelezz 10y agoWhen I first learned C#, I was having a hard time to navigate the code due to partial methods. So I have always wondered what C# developers think of having their methods spread out in different files.
- aanm1988 10y agoIt's a tool to use. Like others have said, it makes working with generated code easier.
- dragonwriter 10y agoPartial classes and partial methods exist specifically to support having code that is automatically generated paired with a human-managed source file. While you could use the support for them to split human-managed code across separate source files, that would be a horrible practice that I've never encountered in the wild, even in .NET shops with otherwise-atrocious practices and code quality.
- jasode 10y ago>While you could use the support for them to split human-managed code across separate source files, that would be a horrible practice To continue that type of advice, some say "#region/#endregion" is another language feature that's intended for code generators so that the IDE can collapse specific lines of code and hide it from view. Programmers should not be hand-coding "#region" themselves. That said, there is debate on that: https://softwareengineering.stackexchange.com/questions/53086/are-regions-an-antipattern-or-code-smell https://softwareengineering.stackexchange.com/questions/5308...
- dragonwriter 10y ago#region / #endregion, IME, largely serves to mitigate the visual offensiveness of poor (usually, completely neglected) design and (despite the potential utility in the case of code generation, and the utility it might have in the rare case where there is a good reason for a monster source file) I'd prefer it not to exist.
- jackmott 10y agoThank you. It has just occurred to me I can use this feature at work! lol
- psyc 10y agoThat's where every Visual Studio dev will see them used, because it's been a VS pattern since the beginning. But I create them manually often enough. Overall I use them sparingly, but there are cases where you definitely want a set of things in one class for code-organization, but still want to think of them as different modules for human-organization.
- tigershark 10y agoIf you want to think of them as different modules then most likely they should be completely separated entities. Why on earth you would want something completely different to live in the same class? It is just screaming that it wants to be a separate class. Namespaces are the correct tool for code organisations, certainly not partial classes.
- psyc 10y agoIt's very interesting that you were able to see my use cases and come to this conclusion...
- tigershark 10y agoRegardless of the use case this is what the official documentation says about namespaces: The namespace keyword is used to declare a scope that contains a set of related objects. You can use a namespace to organize code elements and to create globally unique types. And about partial classes: There are several situations when splitting a class definition is desirable: When working on large projects, spreading a class over separate files enables multiple programmers to work on it at the same time. When working with automatically generated source, code can be added to the class without having to recreate the source file. Visual Studio uses this approach when it creates Windows Forms, Web service wrapper code, and so on. You can create code that uses these classes without having to modify the file created by Visual Studio. As you can see partial classes are not the right tool to organise code.
- psyc 10y ago
- sbergot 10y agoNot the OP but here are my 2 cents: partial classes should only be used when you have a mix of generated and hand written code. Any other usage should be forbidden. It requires some education but it is useful for this usecase.
- Someone 10y agoIf, like me, you're old enough to have used MFC (where the code generators generated source for classes that you had to augment, and randomly picked lines to replace or overwrite in those classes whenever it felt doing so (1), you think they are a godsend. (1) that's an exaggeration; MFC used comments to identify sections that it owned in the source, but in my (limited) experience, there typically were zillions of ways to make changes to your code, but if you didn't use the one Microsoft picked as _the_ way (and which they didn't push into your face in the IDE), you were in for heaps of problems.
- aanm1988 10y agoand amazingly despite all these apparently horribly complex choices that programmers won't understand, it's a great language to work in. Maybe guys like Gosling and Pike should take note. A touch more complexity in the right places can make a huge difference.
- emodendroket 10y agoNot having type erasure is pretty nice (except that reflection code with generics is really hairy).
- josteink 10y agoHairy yes, but really, really powerful.
- rjeli 10y agoI like type erasure and depend on it a lot for Scala and Clojure interop. Any JVM language works with the same objects and methods, and can implement its own type system/syntax on top.
- emodendroket 10y agoThat's true in the clr too as long as everything supports generics.
- paulddraper 10y agoThings that have CLR-like generics work on the CLR. Anything else doesn't. E.g. Scala.
- noblethrasher 10y agoF* has an advanced type system with support for dependent types and refinement types. Yet, it runs on the CLR. Source: https://www.fstar-lang.org https://www.fstar-lang.org
- emodendroket 10y agoI don't really get the complaint. Even if they had type erasure you couldn't use Scala in the CLR because nobody has written a CLR target. And on the other hand, I don't know why there couldn't be a Scala implementation with true generics. A lot of crap like DummyImplicit and ClassTag is there for no other reason than to work around those limitations anyway.
- masklinn 10y ago> + no checked exceptions (checked exceptions have benefits in theory but real-world practice shows that it forces programmers to copy-paste mindless boilerplate to satisfy the checked-constraint) As languages like Rust or Swift demonstrate, the issue is less the checked exceptions and more the abject lack of support for them in the language and type system, which ends up making them essentially unusable. > Gosling said that unsigned types are confusing and dangerous He is right of course, but he forgets that so are signed types if they're bounded. If Java had unbounded signed integers (à la Python or Erlang) that'd be one thing, but Java does not, and neither does it have Pascal-style restrictions/user-defined integral bounds, which means it's no less confusing or dangerous, it's just more limited.
- kjksf 10y agoNeither Swift nor Rust have exceptions, checked or otherwise. The kind of exceptions that unwind the stack until some part of the code up the stack catches the exception. They both handle errors by returning error values, kind of like Go. Rust has a try! macro, which might make you think it's try/catch equivalent, but it's not. It's just a syntactic sugar over error values. Similarly in Swift try/catch/throw is just syntactic sugar for handling error values. https://doc.rust-lang.org/book/error-handling.html https://doc.rust-lang.org/book/error-handling.html https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html https://developer.apple.com/library/content/documentation/Sw...
- masklinn 10y ago> Neither Swift nor Rust have exceptions, checked or otherwise. The point is that both of them have generic error types which "infect" every caller (transitively) in much the way checked exceptions do. That Rust and Swift require explicitly bubbling error values should be a point in favour of checked exceptions.
- mrec 10y agoAs I see it, the Rust (etc) approach avoids two problems: 1. The C problem of forgetting to check error returns. Yes, exceptions (checked or not) also avoid this. 2. The C++/Java/C# problem of exceptions being more expensive than you'd like for common error situations. .NET has sprouted alternatives like `bool tryParse(String, out int)` as a workaround, but on balance I prefer the unified mechanism. What I don't like is how innocuous `unwrap` looks, or how often it appears in example code.
- com2kid 10y ago> + unsigned types (very handy for P/Invoke API boundaries because legacy Win32 has unsigned params everywhere; yes, yes, Gosling said that unsigned types are confusing and dangerous but nevertheless, they are still very useful) The lack of unsigned types in Java is a constant pain when doing cross platform development, or when trying to consume (or write out!) a binary wire format. It can be worked around, but it is just needlessly stupid.
- specialist 10y agoJava's virtual by default methods has never been an issue for me. On the other hand, some clown making their classes and methods final has been a recurring thorn. David Bacon's Kava's approach to lightweight objects remains the correct answer and is sorely missed. The only case for unchecked exception is mitigating terrible design choices. Like using Spring or Hibernate/JPA. When the client code can't do anything with a caught exception, it shouldn't even be thrown. Meaning, they're doing it wrong. The omission of signed integers has caused me unnecessary pain a few times. Original bindings for OpenGL, a DICOM parser, etc. -- Properties are the one C# feature sorely missed in Java. JavaBeans is silly. Syntactic sugar for reflection would be nice, maybe something like 'Method m = myClass#myMethod( String )'. Java has done plenty of terrible things, crimes against productivity and design rationality. Chiefly annotations, lambdas, and the silly Optional. C#'s equivalent quixotic fever dream is probably LINQ. I have a laundry list for Java, JDK (especially), and JVM. Who doesn't? Mostly undoing bad ideas and culling deprecated stuff, plus some sugar to reduce the verbosity. -- Unfortunately, Java's language is hard to separate from its culture. The taint of all the enterprise minded stuff (XML XSD etc, J2EE, Spring, excess indirection caused by design pattern newbies) has been hard to shake off.
- douche 10y ago> C#'s equivalent quixotic fever dream is probably LINQ. Maybe the weird query-style syntax. If you use it properly, it's no different than map, fold, filter, etc that are ubiquitous functional higher-order functions., just with T-SQL-ly names. Linq is so much better than doing all of what it does by hand, with for loops and temporaries galore, the way we once did.
- JamesNK 10y ago> C#'s equivalent quixotic fever dream is probably LINQ. What? LINQ is terrific.