C# vs Java - Generic Lists - c#

What are the differences of the C# and Java implementations of the generic List class?

Well, in Java List<T> is an interface, to start with :)
The most important difference between the two is the difference between C# and Java generics to start with: in Java generics basically perform compile-time checks and include some metadata in generic fields etc - but the actual object doesn't know its generic type at execution time. You can't ask a List<?> what that ? is, in other words. Any references to a generic type parameter in the implementation act as Object, basically - so a ArayList<String> is really backed by an Object[]. In C# all the information is available at execution time too - so a List<string> is backed by a string[].
Similarly C# generics allow value type type arguments, so you can have a List<int> in C# but not in Java.
There are further differences in terms of variance etc - but this is moving a long way from List<T>.
In terms of just ArrayList<T> (Java) and List<T> (.NET), a couple of differences:
Java lists override equals/hashCode, whereas they don't in .NET
ArrayList<T> grows by multiplying the current capacity by 3/2; .NET's List<T> doubles the current capacity instead
Of course there are other differences in terms of the APIs exposed - if you could give more information about the kind of difference you're interested in, we could help more.

Are you asking for differences in their API or their underlying implementation? I believe Java generics are implemented completely via the compiler -- the JVM has no notion of generics. For C#, generics are a built-in concept of the .Net runtime. Wikipedia seems to have a good comparison of the two: http://en.wikipedia.org/wiki/Comparison_of_C_Sharp_and_Java#Generics

Related

Why there's no possible conversion (generic type restricted with interface)? [duplicate]

I didn't attend PDC 2008, but I heard some news that C# 4.0 is announced to support Generic covariance and contra-variance. That is, List<string> can be assigned to List<object>. How could that be?
In Jon Skeet's book C# in Depth, it is explained why C# generics doesn't support covariance and contra-variance. It is mainly for writing secure code. Now, C# 4.0 changed to support them. Would it bring chaos?
Anybody know the details about C# 4.0 can give some explanation?
Variance will only be supported in a safe way - in fact, using the abilities that the CLR already has. So the examples I give in the book of trying to use a List<Banana> as a List<Fruit> (or whatever it was) still won't work - but a few other scenarios will.
Firstly, it will only be supported for interfaces and delegates.
Secondly, it requires the author of the interface/delegate to decorate the type parameters as in (for contravariance) or out (for covariance). The most obvious example is IEnumerable<T> which only ever lets you take values "out" of it - it doesn't let you add new ones. That will become IEnumerable<out T>. That doesn't hurt type safety at all, but lets you return an IEnumerable<string> from a method declared to return IEnumerable<object> for instance.
Contravariance is harder to give concrete examples for using interfaces, but it's easy with a delegate. Consider Action<T> - that just represents a method which takes a T parameter. It would be nice to be able to convert seamlessly use an Action<object> as an Action<string> - any method which takes an object parameter is going to be fine when it's presented with a string instead. Of course, C# 2 already has covariance and contravariance of delegates to some extent, but via an actual conversion from one delegate type to another (creating a new instance) - see P141-144 for examples. C# 4 will make this more generic, and (I believe) will avoid creating a new instance for the conversion. (It'll be a reference conversion instead.)
Hope this clears it up a bit - please let me know if it doesn't make sense!
Not that Jon hasn't already covered it, but here are some links to blogs and videos from Eric Lippert. He does a nice job of explaining it with examples.
https://blogs.msdn.microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c-part-one/
The videos:
https://www.youtube.com/watch?v=3MQDrKbzvqU
https://www.youtube.com/watch?v=XRIadQaBYlI
https://www.youtube.com/watch?v=St9d2EDZfrg

Comparison between IList and IList<object> - should any be preferred?

Since many years, we use generic collections most of the time. Sometimes we really do need a collection of anything (well, usually only a few different things but with no common base class). For such circumstances we can use either IList or the generic IList<object> as type for method arguments and properties.
Is there any reason to prefer one over the other? Performance characteristics?
Personally, I'm leaning towards IList<object>, as I think this makes it more clear that we really do accept "anything". When a parameter is typed as IList we cannot immediately tell if this method do accept anything, or if the lack of generics is due to history or sloppy coding.
There's a good reason: LINQ and its extension methods. These aren't implemented for pre-generics era types. You will need to call Cast<T> on the IList to take advantage of LINQ!
Other point is that, since newest .NET versions support covariance and contravariance and most of generic interfaces support one or the other (f.e. IEnumerable<out T>, T is covariant), you can easily downcast or upcast interfaces' generic parameters from and to object or a less-unspecific type.
Conclusion: why generics should be prefered?
Generic types have better performance because they avoid a lot of casts.
Newer APIs rely on generic collections and interfaces.
There're a lot of reasons to think that mixing objects of different types in the same list could be dangerous and a bad coding/design decision. And for the few cases where you'll store any kind of object, having LINQ and many other newer APIs and features as your friend is a powerful reason to don't reinvent wheels and save a lot of time!

Java language features which have no equivalent in C#

Having mostly worked with C#, I tend to think in terms of C# features which aren't available in Java. After working extensively with Java over the last year, I've started to discover Java features that I wish were in C#. Below is a list of the ones that I'm aware of. Can anyone think of other Java language features which a person with a C# background may not realize exists?
The articles http://www.25hoursaday.com/CsharpVsJava.html and http://en.wikipedia.org/wiki/Comparison_of_Java_and_C_Sharp give a very extensive list of differences between Java and C#, but I wonder whether I missed anything in the (very) long articles. I can also think of one feature (covariant return type) which I didn't see mentioned in either article.
Please limit answers to language or core library features which can't be effectively implemented by your own custom code or third party libraries.
Covariant return type - a method can be overridden by a method which returns a more specific type. Useful when implementing an interface or extending a class and you want an overriding method to return a type more specific to your class. This can be simulated using explicit interface implementation in C#, but there's no simple equivalent when overriding class methods.
Enums are classes - an enum is a full class in java, rather than a wrapper around a primitive like in .Net. Java allows you to define fields and methods on an enum.
Anonymous inner classes - define an anonymous class which implements a method. Although most of the use cases for this in Java are covered by delegates in .Net, there are some cases in which you really need to pass multiple callbacks as a group. It would be nice to have the choice of using an anonymous inner class.
Checked exceptions - I can see how this is useful in the context of common designs used with Java applications, but my experience with .Net has put me in a habit of using exceptions only for unrecoverable conditions. I.E. exceptions indicate a bug in the application and are only caught for the purpose of logging. I haven't quite come around to the idea of using exceptions for normal program flow.
strictfp - Ensures strict floating point arithmetic. I'm not sure what kind of applications would find this useful.
fields in interfaces - It's possible to declare fields in interfaces. I've never used this.
static imports - Allows one to use the static methods of a class without qualifying it with the class name. I just realized today that this feature exists. It sounds like a nice convenience.
Java has packages that reflect a hierarchy and filesystem layout, while in C# the assemblies are irrespective of the namespace hierarchy.
Octal literals! :D
int x = 0245; System.out.println(x);
165 is outputted. Fun :)
Java's generics allow type wildcards. For example, <T extends Object & Comparable<? super T>> T Collections.max(Collection<? extends T>) { ... } is not expressable in C#.
In C#, you cannot have a return statement in a finally block.
I don't know if you want this in your language, but I guess Type Erasure can be seen as a feature to some.

C# vs Java generics [duplicate]

This question already has answers here:
What are the differences between Generics in C# and Java... and Templates in C++? [closed]
(13 answers)
Closed 9 years ago.
I have heard that the Java implementation of Generics is not as good as the C# implementation. In that the syntax looks similar, what is it that is substandard about the Java implementation, or is it a religious point of view?
streloksi's link does a great job of breaking down the differences. The quick and dirty summary though is ...
In terms of syntax and usage. The syntax is roughly the same between the languages. A few quirks here and there (most notably in constraints). But basically if you can read one, you can likely read/use the other.
The biggest difference though is in the implementation.
Java uses the notion of type erasure to implement generics. In short the underlying compiled classes are not actually generic. They compile down to Object and casts. In effect Java generics are a compile time artifact and can easily be subverted at runtime.
C# on the other hand, by virtue of the CLR, implement generics all they way down to the byte code. The CLR took several breaking changes in order to support generics in 2.0. The benefits are performance improvements, deep type safety verification and reflection.
Again the provided link has a much more in depth breakdown I encourage you to read
The difference comes down to a design decision by Microsoft and Sun.
Generics in Java is implemented through type erasure by the compiler, which means that the type checking occurs at compile time, and the type information is removed. This approach was taken to keep the legacy code compatible with new code using generics:
From The Java Tutorials, Generics: Type Erasure:
When a generic type is instantiated,
the compiler translates those types by
a technique called type erasure — a
process where the compiler removes all
information related to type parameters
and type arguments within a class or
method. Type erasure enables Java
applications that use generics to
maintain binary compatibility with
Java libraries and applications that
were created before generics.
However, with generics in C# (.NET), there is no type erasure by the compiler, and the type checks are performed during runtime. This has its benefits that the type information is preserved in the compiled code.
From Wikipedia:
This design choice is leveraged to
provide additional functionality, such
as allowing reflection with
preservation of generic types, as well
as alleviating some of the limitations
of erasure (such as being unable to
create generic arrays). This
also means that there is no
performance hit from runtime casts and
normally expensive boxing conversions.
Rather than saying ".NET generics is better than Java generics", one should look into the difference in the approach to implement generics. In Java, it appears that preserving compatibility was a high priority, while in .NET (when introduced at version 2.0), the realizing the full benefit of using generics was a higher priority.
Also found this conversation with Anders Hejlsberg that may be interesting too. To summarize points that Anders Hejlsberg made with some additional notes: Java generics were made for maximum compatibility with existing JVM that led to few odd things versus implementation you see in C#:
Type erasure forces implementation to represent every generic parametrized value as Object. While compiler provides automatic casts between Object and more specific type, it does not remove the negative impact of the type casts and boxing on performance (e.g. Object is cast to specific type MyClass or int had to be boxed in Integer, which would be even more serious for C#/.NET if they followed type erasure approach due to user-defined value types). As Anders said: "you don't get any of the execution efficiency" (that reified generics enable in C#)
Type erasure makes information available at compile time not accessible during runtime. Something that used to be List<Integer> becomes just a List with no way to recover generic type parameter at runtime. This makes difficult to build reflection or dynamic code-generation scenarios around Java generics. More recent SO answer shows a way around it via anonymous classes. But without tricks, something like generating code at runtime via reflection that gets elements from one collection instance and puts it to another collection instance can fail at runtime during execution of dynamically generated code: reflection doesn't help with catching mismatch in List<Double> versus List<Integer> in these situations.
But +1 for the answer linking to Jonathan Pryor's blog post.

What are the differences between Generics in C# and Java... and Templates in C++? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Closed 9 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I mostly use Java and generics are relatively new. I keep reading that Java made the wrong decision or that .NET has better implementations etc. etc.
So, what are the main differences between C++, C#, Java in generics? Pros/cons of each?
I'll add my voice to the noise and take a stab at making things clear:
C# Generics allow you to declare something like this.
List<Person> foo = new List<Person>();
and then the compiler will prevent you from putting things that aren't Person into the list.
Behind the scenes the C# compiler is just putting List<Person> into the .NET dll file, but at runtime the JIT compiler goes and builds a new set of code, as if you had written a special list class just for containing people - something like ListOfPerson.
The benefit of this is that it makes it really fast. There's no casting or any other stuff, and because the dll contains the information that this is a List of Person, other code that looks at it later on using reflection can tell that it contains Person objects (so you get intellisense and so on).
The downside of this is that old C# 1.0 and 1.1 code (before they added generics) doesn't understand these new List<something>, so you have to manually convert things back to plain old List to interoperate with them. This is not that big of a problem, because C# 2.0 binary code is not backwards compatible. The only time this will ever happen is if you're upgrading some old C# 1.0/1.1 code to C# 2.0
Java Generics allow you to declare something like this.
ArrayList<Person> foo = new ArrayList<Person>();
On the surface it looks the same, and it sort-of is. The compiler will also prevent you from putting things that aren't Person into the list.
The difference is what happens behind the scenes. Unlike C#, Java does not go and build a special ListOfPerson - it just uses the plain old ArrayList which has always been in Java. When you get things out of the array, the usual Person p = (Person)foo.get(1); casting-dance still has to be done. The compiler is saving you the key-presses, but the speed hit/casting is still incurred just like it always was.
When people mention "Type Erasure" this is what they're talking about. The compiler inserts the casts for you, and then 'erases' the fact that it's meant to be a list of Person not just Object
The benefit of this approach is that old code which doesn't understand generics doesn't have to care. It's still dealing with the same old ArrayList as it always has. This is more important in the java world because they wanted to support compiling code using Java 5 with generics, and having it run on old 1.4 or previous JVM's, which microsoft deliberately decided not to bother with.
The downside is the speed hit I mentioned previously, and also because there is no ListOfPerson pseudo-class or anything like that going into the .class files, code that looks at it later on (with reflection, or if you pull it out of another collection where it's been converted into Object or so on) can't tell in any way that it's meant to be a list containing only Person and not just any other array list.
C++ Templates allow you to declare something like this
std::list<Person>* foo = new std::list<Person>();
It looks like C# and Java generics, and it will do what you think it should do, but behind the scenes different things are happening.
It has the most in common with C# generics in that it builds special pseudo-classes rather than just throwing the type information away like java does, but it's a whole different kettle of fish.
Both C# and Java produce output which is designed for virtual machines. If you write some code which has a Person class in it, in both cases some information about a Person class will go into the .dll or .class file, and the JVM/CLR will do stuff with this.
C++ produces raw x86 binary code. Everything is not an object, and there's no underlying virtual machine which needs to know about a Person class. There's no boxing or unboxing, and functions don't have to belong to classes, or indeed anything.
Because of this, the C++ compiler places no restrictions on what you can do with templates - basically any code you could write manually, you can get templates to write for you.
The most obvious example is adding things:
In C# and Java, the generics system needs to know what methods are available for a class, and it needs to pass this down to the virtual machine. The only way to tell it this is by either hard-coding the actual class in, or using interfaces. For example:
string addNames<T>( T first, T second ) { return first.Name() + second.Name(); }
That code won't compile in C# or Java, because it doesn't know that the type T actually provides a method called Name(). You have to tell it - in C# like this:
interface IHasName{ string Name(); };
string addNames<T>( T first, T second ) where T : IHasName { .... }
And then you have to make sure the things you pass to addNames implement the IHasName interface and so on. The java syntax is different (<T extends IHasName>), but it suffers from the same problems.
The 'classic' case for this problem is trying to write a function which does this
string addNames<T>( T first, T second ) { return first + second; }
You can't actually write this code because there are no ways to declare an interface with the + method in it. You fail.
C++ suffers from none of these problems. The compiler doesn't care about passing types down to any VM's - if both your objects have a .Name() function, it will compile. If they don't, it won't. Simple.
So, there you have it :-)
C++ rarely uses the “generics” terminology. Instead, the word “templates” is used and is more accurate. Templates describes one technique to achieve a generic design.
C++ templates is very different from what both C# and Java implement for two main reasons. The first reason is that C++ templates don't only allow compile-time type arguments but also compile-time const-value arguments: templates can be given as integers or even function signatures. This means that you can do some quite funky stuff at compile time, e.g. calculations:
template <unsigned int N>
struct product {
static unsigned int const VALUE = N * product<N - 1>::VALUE;
};
template <>
struct product<1> {
static unsigned int const VALUE = 1;
};
// Usage:
unsigned int const p5 = product<5>::VALUE;
This code also uses the other distinguished feature of C++ templates, namely template specialization. The code defines one class template, product that has one value argument. It also defines a specialization for that template that is used whenever the argument evaluates to 1. This allows me to define a recursion over template definitions. I believe that this was first discovered by Andrei Alexandrescu.
Template specialization is important for C++ because it allows for structural differences in data structures. Templates as a whole is a means of unifying an interface across types. However, although this is desirable, all types cannot be treated equally inside the implementation. C++ templates takes this into account. This is very much the same difference that OOP makes between interface and implementation with the overriding of virtual methods.
C++ templates are essential for its algorithmic programming paradigm. For example, almost all algorithms for containers are defined as functions that accept the container type as a template type and treat them uniformly. Actually, that's not quite right: C++ doesn't work on containers but rather on ranges that are defined by two iterators, pointing to the beginning and behind the end of the container. Thus, the whole content is circumscribed by the iterators: begin <= elements < end.
Using iterators instead of containers is useful because it allows to operate on parts of a container instead of on the whole.
Another distinguishing feature of C++ is the possibility of partial specialization for class templates. This is somewhat related to pattern matching on arguments in Haskell and other functional languages. For example, let's consider a class that stores elements:
template <typename T>
class Store { … }; // (1)
This works for any element type. But let's say that we can store pointers more effciently than other types by applying some special trick. We can do this by partially specializing for all pointer types:
template <typename T>
class Store<T*> { … }; // (2)
Now, whenever we instance a container template for one type, the appropriate definition is used:
Store<int> x; // Uses (1)
Store<int*> y; // Uses (2)
Store<string**> z; // Uses (2), with T = string*.
Anders Hejlsberg himself described the differences here "Generics in C#, Java, and C++".
There are already a lot of good answers on what the differences are, so let me give a slightly different perspective and add the why.
As was already explained, the main difference is type erasure, i.e. the fact that the Java compiler erases the generic types and they don't end up in the generated bytecode. However, the question is: why would anyone do that? It doesn't make sense! Or does it?
Well, what's the alternative? If you don't implement generics in the language, where do you implement them? And the answer is: in the Virtual Machine. Which breaks backwards compatibility.
Type erasure, on the other hand, allows you to mix generic clients with non-generic libraries. In other words: code that was compiled on Java 5 can still be deployed to Java 1.4.
Microsoft, however, decided to break backwards compatibility for generics. That's why .NET Generics are "better" than Java Generics.
Of course, Sun aren't idiots or cowards. The reason why they "chickened out", was that Java was significantly older and more widespread than .NET when they introduced generics. (They were introduced roughly at the same time in both worlds.) Breaking backwards compatibility would have been a huge pain.
Put yet another way: in Java, Generics are a part of the Language (which means they apply only to Java, not to other languages), in .NET they are part of the Virtual Machine (which means they apply to all languages, not just C# and Visual Basic.NET).
Compare this with .NET features like LINQ, lambda expressions, local variable type inference, anonymous types and expression trees: these are all language features. That's why there are subtle differences between VB.NET and C#: if those features were part of the VM, they would be the same in all languages. But the CLR hasn't changed: it's still the same in .NET 3.5 SP1 as it was in .NET 2.0. You can compile a C# program that uses LINQ with the .NET 3.5 compiler and still run it on .NET 2.0, provided that you don't use any .NET 3.5 libraries. That would not work with generics and .NET 1.1, but it would work with Java and Java 1.4.
Follow-up to my previous posting.
Templates are one of the main reasons why C++ fails so abysmally at intellisense, regardless of the IDE used. Because of template specialization, the IDE can never be really sure if a given member exists or not. Consider:
template <typename T>
struct X {
void foo() { }
};
template <>
struct X<int> { };
typedef int my_int_type;
X<my_int_type> a;
a.|
Now, the cursor is at the indicated position and it's damn hard for the IDE to say at that point if, and what, members a has. For other languages the parsing would be straightforward but for C++, quite a bit of evaluation is needed beforehand.
It gets worse. What if my_int_type were defined inside a class template as well? Now its type would depend on another type argument. And here, even compilers fail.
template <typename T>
struct Y {
typedef T my_type;
};
X<Y<int>::my_type> b;
After a bit of thinking, a programmer would conclude that this code is the same as the above: Y<int>::my_type resolves to int, therefore b should be the same type as a, right?
Wrong. At the point where the compiler tries to resolve this statement, it doesn't actually know Y<int>::my_type yet! Therefore, it doesn't know that this is a type. It could be something else, e.g. a member function or a field. This might give rise to ambiguities (though not in the present case), therefore the compiler fails. We have to tell it explicitly that we refer to a type name:
X<typename Y<int>::my_type> b;
Now, the code compiles. To see how ambiguities arise from this situation, consider the following code:
Y<int>::my_type(123);
This code statement is perfectly valid and tells C++ to execute the function call to Y<int>::my_type. However, if my_type is not a function but rather a type, this statement would still be valid and perform a special cast (the function-style cast) which is often a constructor invocation. The compiler can't tell which we mean so we have to disambiguate here.
Both Java and C# introduced generics after their first language release. However, there are differences in how the core libraries changed when generics was introduced. C#'s generics are not just compiler magic and so it was not possible to generify existing library classes without breaking backwards compatibility.
For example, in Java the existing Collections Framework was completely genericised. Java does not have both a generic and legacy non-generic version of the collections classes. In some ways this is much cleaner - if you need to use a collection in C# there is really very little reason to go with the non-generic version, but those legacy classes remain in place, cluttering up the landscape.
Another notable difference is the Enum classes in Java and C#. Java's Enum has this somewhat tortuous looking definition:
// java.lang.Enum Definition in Java
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
(see Angelika Langer's very clear explanation of exactly why this is so. Essentially, this means Java can give type safe access from a string to its Enum value:
// Parsing String to Enum in Java
Colour colour = Colour.valueOf("RED");
Compare this to C#'s version:
// Parsing String to Enum in C#
Colour colour = (Colour)Enum.Parse(typeof(Colour), "RED");
As Enum already existed in C# before generics was introduced to the language, the definition could not change without breaking existing code. So, like collections, it remains in the core libraries in this legacy state.
11 months late, but I think this question is ready for some Java Wildcard stuff.
This is a syntactical feature of Java. Suppose you have a method:
public <T> void Foo(Collection<T> thing)
And suppose you don't need to refer to the type T in the method body. You're declaring a name T and then only using it once, so why should you have to think of a name for it? Instead, you can write:
public void Foo(Collection<?> thing)
The question-mark asks the the compiler to pretend that you declared a normal named type parameter that only needs to appear once in that spot.
There's nothing you can do with wildcards that you can't also do with a named type parameter (which is how these things are always done in C++ and C#).
Wikipedia has great write-ups comparing both Java/C# generics and Java generics/C++ templates. The main article on Generics seems a bit cluttered but it does have some good info in it.
The biggest complaint is type erasure. In that, generics are not enforced at runtime. Here's a link to some Sun docs on the subject.
Generics are implemented by type
erasure: generic type information is
present only at compile time, after
which it is erased by the compiler.
C++ templates are actually much more powerful than their C# and Java counterparts as they are evaluated at compile time and support specialization. This allows for Template Meta-Programming and makes the C++ compiler equivalent to a Turing machine (i.e. during the compilation process you can compute anything that is computable with a Turing machine).
In Java, generics are compiler level only, so you get:
a = new ArrayList<String>()
a.getClass() => ArrayList
Note that the type of 'a' is an array list, not a list of strings. So the type of a list of bananas would equal() a list of monkeys.
So to speak.
Looks like, among other very interesting proposals, there is one about refining generics and breaking backwards compatibility:
Currently, generics are implemented
using erasure, which means that the
generic type information is not
available at runtime, which makes some
kind of code hard to write. Generics
were implemented this way to support
backwards compatibility with older
non-generic code. Reified generics
would make the generic type
information available at runtime,
which would break legacy non-generic
code. However, Neal Gafter has
proposed making types reifiable only
if specified, so as to not break
backward compatibility.
at Alex Miller's article about Java 7 Proposals
NB: I don't have enough point to comment, so feel free to move this as a comment to appropriate answer.
Contrary to popular believe, which I never understand where it came from, .net implemented true generics without breaking backward compatibility, and they spent explicit effort for that.
You don't have to change your non-generic .net 1.0 code into generics just to be used in .net 2.0. Both the generic and non-generic lists are still available in .Net framework 2.0 even until 4.0, exactly for nothing else but backward compatibility reason. Therefore old codes that still used non-generic ArrayList will still work, and use the same ArrayList class as before.
Backward code compatibility is always maintained since 1.0 till now... So even in .net 4.0, you still have to option to use any non-generics class from 1.0 BCL if you choose to do so.
So I don't think java has to break backward compatibility to support true generics.

Categories

Resources