Talk:Comparison of C Sharp and Java/Archive 2: Difference between revisions

Content deleted Content added
MiszaBot I (talk | contribs)
m Archiving 6 thread(s) from Talk:Comparison of C Sharp and Java.
MiszaBot I (talk | contribs)
m Archiving 1 thread(s) from Talk:Comparison of C Sharp and Java. (ARCHIVE FULL)
Line 339:
:::::: I think you are under a misconception. Even Microsoft, when comparing how C# and Java do with event handling, do not consider java events as second class citizens[http://msdn.microsoft.com/en-us/library/ms228499%28VS.90%29.aspx]. I don't think that you will find a lot of reliable sources explaining that events are second class citizens in Java. However, if you can find those, I'm OK with that. This is not about how we feel it shluld be, for you and of course also for me. [[User:Hervegirod|Hervegirod]] ([[User talk:Hervegirod|talk]]) 23:44, 7 December 2010 (UTC)
:::::::Could you please try and read my statement again, Hervegirod? You were the one who brought in AWT. My above statement was against including AWT in this article. Note how my statement doesn't say anything about including Java event handling (it is after all not in AWT but in java.util), only about presenting it as a ''language feature''. In C#, event definition and handling is clearly a language feature: The compiler will implement event subscription (adding/removing and combining multicast delegates) for you when you use the ''event'' keyword. C# does so at the language level without assuming anything else about events (like signatures, interfaces etc). C# developers can build upon this ''direct language support'' to build a specific event model. Building a specific event model involves deciding how/if event arguments are specified, how/if the source is identified, deciding if the subscribers and/or publishers must implement specific interfaces or derive from specific base classes etc. The BCL developers did this in System.* where you'll find the ''EventArgs'' class. Note how this latter part is analogous to java.util.* where you find the ''EventListener'' interface, ''EventObject'' class (akin to .NET ''EventArgs''). Because both languages are object oriented then of course the observer/observable pattern ''can'' be implemented. This does not make it a language feature, though. One language (C#) provides standard infrastructure for building any number of event models, all of which will benefit from the language feature - i.e. they will not need to build multicast containers. ''One'' such model is found in the System.* namespace. In Java you lack this infrastructure. You can still build ''any number'' of event models, but ''all'' of them will need to implement multicast containers (subscription lists) specifically for '''each event''' exposed by an object. The implementation in java.util (used by AWT) does not solve this, you still need to build event listener collections for all events exposed by all objects. This is a significant and interesting difference between the languages and certainly noteworthy in a comparison article. Now, whether the comparison table should be green or red depends on how much of the BCL we consider ok for inclusion in this article. If this is just the languages (the syntax and the semantics) then Java has a "no; but the BCL offer specific implementation". If we consider the "core" parts of the BCLs ok for inclusion then Java has a "yes; library feature" and C# has a "yes; language feature". The differences I outlines above can then be explained in the associated prosa. [[User:Useerup|Useerup]] ([[User talk:Useerup|talk]]) 07:48, 8 December 2010 (UTC)
== Value types (again) ==
 
Value types are *not* a C# invention. Even Java has the "primitive" types which has the same semantics. Only Java does not allow developers to specify their own value types, C# does. Value types are not a C# invention, even Pascal and C++ has them. In Pascal they are called "records". C++ has them not as an explicit concept, but any type act as a value type when used as an automatically (stack allocated) variable. So can we please lay this discussion to rest? [[User:Useerup|Useerup]] ([[User talk:Useerup|talk]]) 09:30, 28 November 2010 (UTC)
: There is a big difference between C/C++ structures and value types because structures in C or C++ are passed by reference, and they are passed by value in C#. It's the same in Pascal, where records are passed by reference too. Plus there are two kinds of Value types in C#: structures and enumerations. There are enumerations in Java too. Which means that the Value type line is misleading and incorrect. What would be correct would be to have two lines: structures (C# has, Java has not), and enumerations (the two languages have). There is also a specificity in C# because structures are passed by values (contrary to what is done in other languages which have this concept). I have another problem with the table, and most of the article: with almost NO sources, it is 90% OR, even if I agree that a lot of the text may be right. [[User:Hervegirod|Hervegirod]] ([[User talk:Hervegirod|talk]]) 14:41, 28 November 2010 (UTC)
::I think you may want to read up on C++ and Pascal. If I define a class (or struct) in C++ and declare a local variable of that class, it is *not* a reference; it is an ''automatic'' (look it up) object. It is automatically constructed (using a default constructor) and automatically destroyed. It has copy semantics: If I define another variable of the same type and assigns the forst one to it, C++ will "shallow" copy the members from the 1st object to the 2nd (actually, C++ will just copy the memory representation of the object). Also, C++ passes parameters of such type by value, ''unless'' you explicitly specify a pointer or reference type. Demonstration:
<source lang="cpp">
class Zem
{
public:
char* question;
int answer;
};
 
Zem zem1, zem2;
zem1.question = "The life, universe and everything?";
zem1.answer = 42;
zem2 = zem1;
zem2.question = "What is six times nine?";
std::cout << zem1.question << " " << zem1.answer << std::endl; // outputs "The life, universe and everything? 42"
std::cout << zem2.question << " " << zem2.answer << std::endl; // outputs "What is six times nine? 42"
</source>
::As you can see, zem2 is ''copied'' from zem1, but their "questions" clearly refer to different objects. If they had been copied by reference there would be only one question. [[User:Useerup|Useerup]] ([[User talk:Useerup|talk]]) 07:49, 29 November 2010 (UTC)
 
:: @Hervegirod : "<i>There is a big difference between C/C++ structures and value types because structures in C or C++ are passed by reference</i>" : You're wrong. In C and C++, you can pass a struct by copy:
<source lang="cpp">
// C++ code
 
struct Value
{
int i;
double j;
std::string s;
} ;
 
void foo(Value p_value)
{
// p_value is a copy of the original variable
}
 
void bar()
{
Value value ;
foo(value) ; // value is passed by copy
}
</source>
 
::Fact is, in C++, you can pass whatever you want by copy or reference (my personal preferred curiosity being the reference to a pointer) or even const reference. The "Value Type" semantics exists, too, on C++: Anything pointed to could be considered to not be a value type (a pointed type? ... :-) ...), but all this discussion is blurred by the fact you have references or pointers to a value type, even when allocated on the stack:
 
<source lang="cpp">
// C++ code
 
void foo()
{
int i = 0 ; // "C# value type"/"Java primitive"
int j = i ; // j is now a copy of i, but a distinct one.
int & ri = i ; // ri is an alias/reference to i
int * pi = &i; // pi points to i
 
i += 2 ; // now, ri == 2 (and *pi == 2), but j == 0 [value type semantics]
ri += 3 ; // now, i == 5 (and *pi == 5), but j == 0 [value type semantics]
*pi += 4 ; // now, i == 9 (and ri == 9), but j == 0 [value type semantics]
pi += 4 ; // now, pi is invalid [pointer semantics]
}
</source>
 
:: In C++, the value type (or concrete type) would be something whose meaningful value you access directly.<br />Whereas the pointer type would be something to be access indirectly, through pointer dereferencing, but if you play directly with the pointer (i.e. its address value), then lose its meaningful value (and in the example above, you have a bug). <b>So there is a notion of value types vs. pointed types in C++ (which mirrors the difference between value types and reference types in Java/C#)</b>.<br /><br />[[User:Paercebal|Paercebal]] ([[User talk:Paercebal|talk]]) 15:12, 23 April 2011 (UTC)
 
I confirm about value types being an important topic. Two examples comparing Java and C# code. Please bear in mind that the point is to use light-weight types (as in: not using the GC or boxing/unboxing as much as possible):
 
In Java and C#, the "Value Type" is an existing language concept (called primitive in Java).
 
This can be summed up to: Do you access the data through a reference, or do you access it directly? But despite their similarity, C# Value Types and Java primitives have some important differences:
 
<b>C# Value Types are C# objects, whereas Java primitives are not Java objects, meaning C# can (and does handle) Value Types both efficiently and genericly, whereas Java cannot handle primitives both efficiently and genericly.</b>
 
For example, for build-in value/primitive types:
<source lang="java">
// Java code
 
void foo()
{
// testing a build-in primitive
int i = 42 ;
 
// testing Object Oriented properties of a Java primitive
i.toString() ; // WON'T COMPILE because int is not an Object
new Integer(i).toString() ; // will compile, but will be slow: manual boxing involved
// Testing generic containers of java primitives
Vector<int> array = new Vector<int>() ; // WON'T COMPILE !!!
Vector<Integer> array = new Vector<Integer>() ; // only way to have a vector of ints
 
// Testing boxing/unboxing of java primitives
array.add(i) ; // slow: autoboxing involved
boolean b = array.get(0) == 25 ; // slow: auto-unboxing involved
array.get(0) += 5 ; //WON'T COMPILE !!!
}
</source>
<source lang="csharp">
C# code
 
void foo()
{
// testing a build-in value type
int i = 42 ;
 
// testing Object Oriented properties of a C# value type
i.ToString() ; // fast: no boxing involved
 
// Testing generic containers of C# value types
List<int> array = new List<int>() ;
array.Add(i) ; // fast: no boxing involved
bool b = array[0] == 25 ; // fast: no unboxing involved
array[0] += 5 ; // fast: and now, 1st element of array is 47
}
</source>
The example above shows that C# handle build-in value/primitive types efficiently, and as first class citizens (C# value types have methods, and derive from Object, while Java don't).
 
The example below will show a Java and C# implementation of an aggregation of data. This data needs to be mutable, needs to used in arrays of millions of those those data, and could be used as keys for Hash tables/maps. Being able to handle those data with value copy semantics is important, too (i.e. the assignment creates a deep copy, not a clone).
 
So, for those user-defined types supposed to behave like value/primitive types:
<source lang="java">
// Java code
 
// Of course, there is no way to have user-defined primitives,
// so will use full Java classes instead
 
class MyValueTypeSize
{
public int quantic ;
public double length ;
 
// constructors, methods, etc.
}
 
class MyValueType
{
public boolean truthness ;
// This will need the allocation a separate MyValueTypeSize on the GC heap
public MyValueTypeSize size ;
 
// constructors, methods, etc.
}
 
// etc.
 
void foo()
{
// allocation of one array of contiguous of 1-million references to items
// (i.e. each item will be allocated separately)
int size = 1000000;
MyValueType[] array = new MyValueType[size];
 
for(int i = 0; i < size; ++i)
{
// for the following line
// allocation on GC part: 1 for MyValueType and 1 for MyValueTypeSize
array[i] = new MyValueType(i, 3.1415 * i, (i % 2) == 0);
 
// for the following lines
// to avoid new allocation on GC part, the code must be written
// very carefully. We choose to write a specific method increment
// (there are possibly one increment method for each constructor)
array[i].increment(42);
array[i].increment(true, 5.55);
array[i].increment(i * 25, 0.05 * i, ((i + 1) % 2) == 0);
}
}
</source>
<source lang="csharp">
C# code
 
// testing user-defined value types
 
struct MyValueTypeSize
{
public int Quantic ;
public double Length ;
 
// + constructors, operators, etc., as needed
}
 
struct MyValueType
{
bool Truthness ;
 
// no need for a separate GL allocation for this...
public MyValueTypeSize Size ;
 
// ... so, for all intents, we can consider MyValueType
// to be an aggregation of an int, a double and a bool
// in the same structure
 
// + constructors, operators, etc., as needed
}
 
// etc.
 
void foo()
{
// allocation of one array (whose size is enough to contain 1-million
// contiguous items)
int size = 1000000;
MyValueType[] array = new MyValueType[size];
for(int i = 0; i < size; ++i)
{
// for the following line
// no allocation on GC part.
// Everything is modified in the array
array[i] = new MyValueType(i, 3.1415 * i, (i % 2) == 0);
 
// for the following lines
// no allocation on GC part
// Note that here is only ONE operator + defined to handle the
// following lines, instead of one overload for each MyValueType
// constructor in Java
array[i] += new MyValueType(42);
array[i] += new MyValueType(true, 5.55);
array[i] += new MyValueType(i * 25, 0.05 * i, ((i + 1) % 2) == 0);
}
}
</source>
 
And please note that this difference is not mere plain syntactic sugar: There is a major performance cost involved there (allocating millions of small objects is always a problem, both in speed in low-latency cases, and in memory in large data cases).
 
[[User:Paercebal|Paercebal]] ([[User talk:Paercebal|talk]]) 15:50, 23 April 2011 (UTC)