• Jeremy (unregistered) in reply to Gnome
    Anonymous:
    Generics may sound great but really they are a dirty hack that does not actually provide any type saftey at all.

    List<integer> myList = new ArrayList<integer>();
    List list2 = myList;
    list2.add(new String());

    Code compiles, now iterate through your genericized myList and see what happens.


    Interestingly enough, I get a compiler warning. It warns me that I don't have type safety. And not surprisingly when I run the code that's exactly what's wrong.
    So it doesn't provide type safety IF you choose to ignore the compiler!
    </integer></integer>
  • rponton (unregistered) in reply to OneFactor
    OneFactor:

    Anonymous:
    DisturbedSaint:

    That's not to say that C# doesn't have its own issues with generics...

                List<INT32> myList = new List<INT32>();
                IList myList2 = myList;
                myList2.Add("Hello World!");

    That compiles, but will at least throw an exception when line 3 is hit.

    -ds


    </INT32>Bah.

    Ok, it compiles and does throw an exception.  You just have to include System.Collections as well as System.Collections.Generic.

    I still vote it's misuse of an interface. :)

    </INT32>

    Use or misuse, it means the advertising hype of "type-safe collections" is a myth. It means that "provably safe casting" is right up there with believing in the tooth-fairy.

    The entire point of Generics is to trap these casting errors at compile time rather than runtime. If all we do is reclassify these runtime errors as misuses we haven't really accomplished anything.

    Making the generic lists implement the old list interfaces for backwards compatibility is just daft. Reminds me of the "refused bequest" bad smell in code. Except now the smell is ingrained in the core language of both Java and .Net

    My ILists, the Generics, they do nothing!



    It's a design flaw in the class libraries, not a broken language feature.  The language can't stop a programmer from implementing a class with a poor design.

    If you write your own MyList{T} class that does not implement untyped IList, you'll have type safety.  If you expose your List{T} property publicly as an IList{T} you'll be fine as well, since IList{T} doesn't implement untyped IList.

    Generics in C# work just fine and do give you true type safety.  No language feature will be bulletproof against reckless runtime type casting.  It's the implementation of List{T} that is borked.
  • (cs) in reply to rponton

    Having worked with generics for a while, I'm not sure that they're possible to implement cleanly.  Forget about backwards compatibility.  What can you do when you know that a collection contains a certain class of items but its generic type is a superclass of the content type?  If you need to pass this collection to a method that accepts only the sub-typed collection, I can't think of any efficient solution that doesn't involve working around generic warnings.  If the compiler rejected these hacks, you'd end up with everything declared with the 'Object' type with the same plethora of casts that generics were meant to eliminate.  I haven't been able to create any body of code consisting of more than ~10000 lines that didn't necessitate the occasional generics warning.

  • (cs) in reply to zip
    zip:

    Anonymous:
    So given that C++ has no basic Object class...
    what was this guy doing in C++?

    Void pointers, baby!  Woohoo!



    I almost shot milk out my nose! I've got to learn to not eat or drink anything while I'm reading this forum.
  • (cs)

    Dan's solution still isn't generic enough for me.

    A zero byte file -- now THAT's generic.  You can do anything you want with it!

  • paula (unregistered) in reply to Brian Kemp
    Anonymous:
    So what's worse...generic databases, or generic types?


    if (IsTrue((CObject<Object>)database > (CObject<Object>)type) != FILE_NOT_FOUND)
        print "Paula = brilliant";
    else
        print "File Not Found";
  • Justin Miller (unregistered) in reply to Ragnar

    To my knowledge Java will let you execute code that has compilation errors; at least eclipse does.  Just dont run the class that didn't compile (great late at nite when you really don't care anymore).

  • (cs)

    Heh, static typing is almost a WTF in itself. In a dynamic language, the type is attached to the value, and no amount of passing it around will change what it is. Only a conversion can do that (the WTF-ery of over-eager implicit conversions is another thing). You can hardly blow things up with a type mismatch.

    In fact, that's why I kinda like Java: most things in Java are objects, and objects carry their actual type with them. Type declarations are merely a convenience to ensure some basic compile-time checking. And guess what? They mostly stand in your way.

    Braces for flames

  • (cs)
    Alex Papadimoulis:
    Dictionary<Object, Object>  = new Dictionary<Object, Object>();


    He went to such trouble making the class generic in the first place, he must have wanted to keep it like that wherever he used it as well. Would have been a waste otherwise, wouldn't it? ^_^
  • (cs) in reply to hwaite
    hwaite:
    I can't think of any efficient solution that doesn't involve working around generic warnings.

    Make the method generic as well.

  • John Doe (unregistered) in reply to Gnome
    Anonymous:
    Generics may sound great but really they are a dirty hack that does not actually provide any type saftey at all.

    List<integer> myList = new ArrayList<integer>();
    List list2 = myList;
    list2.add(new String());

    Code compiles, now iterate through your genericized myList and see what happens.


    That reminds me of something i read about objective-c some years ago.
    'Elephants do what elephants do and lemons do what lemons do. Make sure that no elephant, by accident, ends up in your blender for it will surely ruin your breakfast.'

    But, then again, there are languages which allow for the object to change its inheritance at run time. So maybe the blender can be made to force any incoming object to derive from a fruit class? ;-)
    </integer></integer>
  • (cs) in reply to Athas
    Athas:
    Anonymous:
    Generics may sound great but really they are a dirty hack that does not actually provide any type saftey at all.

    List<integer> myList = new ArrayList<integer>();
    List list2 = myList;
    list2.add(new String());

    Code compiles, now iterate through your genericized myList and see what happens.


    If this really does as you say, then it would, in my opinion, be a defect in the implementation of generic programming in C#. C++ would not accept such nonsense. You do not want a supposedly modern, managed language to be less safe than a volcano language like C++. Why aren't the template/generic/type parameters for list2 inferred from the type definition of myList? It should be blindingly obvious to the compiler!</integer></integer>


    Obvious? Oh really? how about

    List intList<int> = new ArrayList<int>();
    List stringList<string> = new ArrayList<string>();
    List list2;
    Random rnd = new Random();
    if (rnd.NextDouble() <= 0.5) {
       list2 = intList;
    } else {
       list2 = stringList;
    }
    list2.add(new String());

    Not so obvious now, eh?
  • (cs) in reply to Zach M
    Anonymous:
    Anonymous:

    List<INTEGER> newList = (List<INTEGER) oldlist="">


    Well I just keep making mistakes I don't know how to display tags in here but I'm meaning something like

    List {Integer} newList = ( List {Integer}) oldList

    please replace { } with greater than, less than signs.

    -Zach
    </INTEGER)></INTEGER>

    After hitting "Reply" or "Quote", click in the "HTML" view before writing anything.

    Now you can use the HTML entities to express those characters:

    < &lt;
    > &gt;
    & &amp;

    Remember to use <p> and </p> for paragraphs so you won't get all your text rendered in a single block.

    Thanks to the first person who told me this. If I just could remember who it was....

  • (cs)
        List<Integer> lista = new List<Integer>();
        List lista2 = lista;
        lista2.add("");
    
    gives this error:
    
    java.util.List is abstract; cannot be instantiated
        List<Integer> lista = new List<Integer>(); 
                              ^
    
    So I used LinkedList, and it worked.
    
    SO I thought "hey, maybe it throws an exception when instatiating a listIterator or adding a value":
    
      List<Integer> lista = new LinkedList<Integer>();
      List lista2 = lista;
      lista2.add("WTF!");
      ListIterator<Integer> it = lista2.listIterator();
      while ( it.hasNext() ) {
        out.println(it.next());
      }
    
    No, it just displays "WTF!"
    
    If I change this line, however:
    
      List<Boolean> lista2 = lista;
    
    then I get an error, but not the expected one (notice that I'm using purposely an incorrect type!):
    
    /index.jsp:15: cannot find symbol
    symbol  : method add(java.lang.String)
    location: interface java.util.List<java.lang.Integer>
      lista2.add("WTF!");
    
    
    And here I was, thinking that Java was a strongly typed language :(
    
    
    
  • (cs) in reply to Enric Naval

    I meant:

    If I change this line, however:
    
      List<Boolean> lista2 = lista;
    
  • (cs) in reply to Justin Miller
    Anonymous:
    To my knowledge Java will let you execute code that has compilation errors; at least eclipse does.


    No, Java will not do that. It's an eclipse feature that basically works by substituting code sections that can't be compiled with throwing a java.lang.Error with the compiler error as its message.
  • Hendrik (unregistered) in reply to WWWWolf
    WWWWolf:
    OneFactor:
    But I really do fear an entirely new species of WTF<exception>


    Today's post was pathetic in that regard, it was almost readable. Hope someone tries harder. Come on! Something worse? You know,  remove-a-space-from-a-funny-location-and-it-won't-compile worse?
    </exception>


    You mean Perl?
  • (cs) in reply to Enric Naval

    Finally, since ListIterator will happily return any sort of object when being instatiated from a generic list, independently of its template type, and against the frigging specification, I thought of asking Java itself what class of object it was returning

      List<Integer> lista = new LinkedList<Integer>();
      List lista2 = lista;
      lista2.add("WTF!");
      ListIterator<Integer> it = lista2.listIterator();
      while ( it.hasNext() ) {
        out.println(it.next().getClass().getSimpleName());
      }
    
    Which returns:
    
    java.lang.ClassCastException: java.lang.String
    at _jsp._index__jsp._jspService(/index.jsp:18)
    
    Great, a ClassCastException, just the kind of exception I wanted to get AT COMPILE TIME (notice that this is only being thrown at run time) and when using the object normally.
    
    
    Well, at least I got this in stdout.log:
    
    [10:53:45.163] Note: /home/----/html/WEB-INF/work/_jsp/_index__jsp.java uses unchecked or unsafe operations.
    [10:53:45.163] Note: Recompile with -Xlint:unchecked for details.
    
    
    I guess I'll have to change the warning level on the JSP server, breaking half the legacy JSP applications on the server.....
    
    
  • C++ guy (unregistered) in reply to John Hensley
    Anonymous:
    So given that C++ has no basic Object class...
    what was this guy doing in C++?
    I think the real question is, what was a C++ guy (if he was a real C++ guy) doing in C# ?
  • (cs) in reply to felix
    felix:
    Heh, static typing is almost a WTF in itself.


    Not at all. Static typing is absolutely needed for big projects. According to my experience, it is impossible (say extremely difficult/expensive) to developp a project without it (let's say >100K SLOC).

    felix:
    In a dynamic language, the type is attached to the value, and no amount of passing it around will change what it is. Only a conversion can do that (the WTF-ery of over-eager implicit conversions is another thing). You can hardly blow things up with a type mismatch.


    Agreed. Dynamic typing is also a must.

    felix:
    Type declarations are merely a convenience to ensure some basic compile-time checking.


    Yes. But it is very very convenient.

    felix:
    And guess what? They mostly stand in your way.


    No. This is the implementation in most languages that is not good and leads you to workarounds. Don't blame static typing just because it is badly used in C# and Java.


  • Jim (unregistered) in reply to trollable
    trollable:
    Not at all. Static typing is absolutely needed for big projects.

    trollable:
    Agreed. Dynamic typing is also a must.


    You're a fan of optional static typing?
  • (cs) in reply to felix
    felix:
    Heh, static typing is almost a WTF in itself. In a dynamic language, the type is attached to the value, and no amount of passing it around will change what it is.

    What does type conversion have to do with static typing?  Come to that, what do type declarations have to do with static typing?  There are plenty of statically-typed languages, like Haskell or ML, that do not permit arbitrary typecasts and do not require type declarations.  In use, they appear just like dynamically-typed languages - except they don't fail unexpectedly at runtime because you passed a function an object of the wrong type.
  • (cs) in reply to trollable
    trollable:
    Not at all. Static typing is absolutely needed for big projects.

    It can certainly be useful, and static typing may be necessary for formal verification, but it really is possible to create large systems, with hundreds of thousands of lines of code, in dynamic languages. Look at various Smalltalk and Lisp-based systems for example (especially the latter). Dynamic typing does not remove the ability to perform type assertations.

  • (cs) in reply to Iago
    Iago:
    What does type conversion have to do with static typing?


    Think of C, which ultimately allows you to treat any value as any type because the type information (weak as it is) is attached to the variables, not the values.

    Iago:
    Come to that, what do type declarations have to do with static typing?  There are plenty of statically-typed languages, like Haskell or ML, that do not permit arbitrary typecasts and do not require type declarations.  In use, they appear just like dynamically-typed languages - except they don't fail unexpectedly at runtime because you passed a function an object of the wrong type.


    I know, that's great, but have you seen the size of the GHC? And how many Haskell compilers exist? Two? Three? There is a price to pay for having such a type system built into the language.

  • (cs) in reply to Maurits

    I'm sure he had written a class called Object and was simply using this custom Object class instead

    ;)

  • (cs) in reply to Corwinoid
    Corwinoid:

    Anonymous:
    That's not exactly true, at least with Java 1.5. Depending on the compiler options you give it (or annotations) you can ignore the compilation errors. In Eclipse however, I have to specify I want the compiler to ignore these errors ...
    -Zach

    The real WTF here is that Java lets you ignore compilation errors.  I can see it now:

    no, the real WTF is that some people don't know the difference between compiler ERRORs and compiler WARNINGs.

    Some IDEs and compilers can be set to treat warnings as errors (so not generate a classfile on encountering them), not the other way around.

  • (cs) in reply to WWWWolf

    WWWWolf:
    OneFactor:
    But I really do fear an entirely new species of WTF<EXCEPTION>


    I bet someone who was kicked out of C++ development due to gross misuse of C++'s template features will find a way to... dare I even suggest... replicate C++'s... expressivity... that both MS and Sun vehemently denied that generics would have.

    Today's post was pathetic in that regard, it was almost readable. Hope someone tries harder. Come on! Something worse? You know,  remove-a-space-from-a-funny-location-and-it-won't-compile worse?


    </EXCEPTION>

    oh, you mean like in C++ where the space in

    vector<vector<int> > vec;
    is mandatory because the compiler will think you are trying to use a bitshift operator if you don't insert it?

  • (cs) in reply to jwenting

    ah, the beauty of the forum software strikes again :)

     

  • (cs) in reply to jwenting
    jwenting:
    jwenting:
    oh, you mean like in C++ where the space in vector<vector<int> > vec; is mandatory because the compiler will think you are trying to use a bitshift operator if you don't insert it?

    ah, the beauty of the forum software strikes again :)

     

    The HTML view, Luke, don't forget about the HTML view.... :)

    Not to mention that the HTML view is below the text area and it is not visible on Opera and on some versions of Firefox, so you'll have to use the dark side of HTML..., err, I mean, you'll have to use Internet Explorer.

  • (cs)

    Why is everybody picking on me?

  • (cs) in reply to trollable
    trollable:
    felix:
    Heh, static typing is almost a WTF in itself.


    Not at all. Static typing is absolutely needed for big projects. According to my experience, it is impossible (say extremely difficult/expensive) to developp a project without it (let's say >100K SLOC).


    Fans of dynamically typed languages argue that static typing prevents only a very limited class of errors, while incurring a great overhead. They prefer their error-prevention overhead in the form of extensive unit tests, which catch far more errors. They have a point, but it does require a lot of discipline since unit tests aren't forced on you by the compiler.

    trollable:
    felix:
    In a dynamic language, the type is attached to the value, and no amount of passing it around will change what it is. Only a conversion can do that (the WTF-ery of over-eager implicit conversions is another thing). You can hardly blow things up with a type mismatch.


    Agreed. Dynamic typing is also a must.


    I think you are confusing the completely separate issues of static/dynamic and strong/weak typing.

    Java has strong static typing
    C/C++ has weak static typing
    VB has weak dynamic typing
    Python has strong dynamic typing

  • (cs) in reply to felix
    felix:
    Heh, static typing is almost a WTF in itself. In a dynamic language, the type is attached to the value, and no amount of passing it around will change what it is. Only a conversion can do that (the WTF-ery of over-eager implicit conversions is another thing). You can hardly blow things up with a type mismatch.

    In fact, that's why I kinda like Java: most things in Java are objects, and objects carry their actual type with them. Type declarations are merely a convenience to ensure some basic compile-time checking. And guess what? They mostly stand in your way.

    *Braces for flames*

    Heh, reminded me of this quote from Brian Foote:

    Dynamic types are stronger than static types, as they don't flee the field at runtime.

    Now, truth to be told, I hate explicit static typing, but static typing with a good type inference is extremely nice.

    Java or C#'s static typing, on the other hand, is more like constraint programming gone bad.

    felix:
    There is a price to pay for having such a type system built into the language.

    Which price, less compilers? Is that such a bad thing?

  • (cs) in reply to Judah
    Anonymous:
    Anonymous:
    zip:

    Anonymous:
    So given that C++ has no basic Object class...
    what was this guy doing in C++?

    Void pointers, baby!  Woohoo!


    My brane just exploded.

    Meh bane jut splode



    Me ayes, dea googles!
  • (cs) in reply to Athas
    Athas:
    Anonymous:
    Generics may sound great but really they are a dirty hack that does not actually provide any type saftey at all.

    List<integer> myList = new ArrayList<integer>();
    List list2 = myList;
    list2.add(new String());

    Code compiles, now iterate through your genericized myList and see what happens.


    If this really does as you say, then it would, in my opinion, be a defect in the implementation of generic programming in C#. C++ would not accept such nonsense. You do not want a supposedly modern, managed language to be less safe than a volcano language like C++. Why aren't the template/generic/type parameters for list2 inferred from the type definition of myList? It should be blindingly obvious to the compiler! And why does C# allow a generic class to be instantiated without proper template/generic/type parameters? Does the compiler at least emit a warning? What's the point of a static language if the compiler doesn't perform bondage-style static checks? Why not just use a fully dynamic language then?
    </integer></integer>


    Let's face it: inheritance and generics don't go well together.
    The only case when they do is when a language is specifically designed to have both. These languages are very strongly type-safe, don't have a father-of-all Object class, class inheritance graphs are not trees but generic forests and all interaction between these two ways of generalization is strictly regulated.

    If you have both Object and generics, no matter how clever the implementation is, anomalies will occur.
    Just for the sake of illustration: If A extends B, does C<A> extend C<B>?
    If it does, you can cast your Collection<String> to Collection<Comparable> and put a nasty non-String in it. (See the quoted code, provided it really works in C#.)
    If it doesn't, you're in all kinds of mess. How do you implement a sort() function for your Collection<Comparable>? One thing is sure: it won't work for your Collection<String>. Eventually you are forced to juggle a bit with the structure of your code. I don't really know how other languages tried to cope with this, Java tried to solve this by using bounded wildcard types. Of course, this method has it's own drawbacks, again forcing you into some weird hacks. (And the less talented you are, the weirder those hacks will be. :))

    All this in the name of clarity and readability.
    Tthe third "advantage", compile-time type safety sounds ok. It's just I've never encountered a single bug caused by putting the wrong type of object into a container, despite having seen (and having been forced to maintain) vast loads of crap code over the year.
    A complicated solution for a non-existent problem, if you ask me.
  • UDontWantToKnow (unregistered) in reply to FriedEggs

    I'm sure his C++ code looks like this:

    std::vector<void*> vector_of_stuff;
    ...

  • (cs) in reply to DisturbedSaint
    DisturbedSaint:
    Anonymous:

    DisturbedSaint:

    I believe he's referring to Java, not C#.  In C#, there is no non-generic form of the List class.  So line #2 above causes a compilation error.

    -ds

    You're right, it's Java.


    That's not to say that C# doesn't have its own issues with generics...

                List<INT32> myList = new List<INT32>();
                IList myList2 = myList;
                myList2.Add("Hello World!");

    That compiles, but will at least throw an exception when line 3 is hit.

    -ds

    Your example really has nothing to with generics.  If I was doing things the old-fashioned, pre-2.0 way, I could cast to a superclass or interface and get exaxtly the same problem.   With generics, I get the strongly typed class without hand-coding the pass-through methods.

  • (cs) in reply to JohnO

    More likely he wrote a generic class object and then put in his C++ code standards that all classes must inhierat from object.

    class object { virtual ~object() {}; };

    class shape : public object { ... };

    class zooAnimal : public object { ... };

    See, now you can have circles and elephants in the same container! Brillant.

  • Pyromancer (unregistered) in reply to UDontWantToKnow

    Anonymous:
    I'm sure his C++ code looks like this:

    std::vector<VOID*> vector_of_stuff;
    ...

    yes,the "old scholl"-style[Y]

    I'm often tempted to do that too

  • Ribbly Screwspigot (unregistered) in reply to Tony Morris

    TextResponse<THEDAILYWTFFORUM> response = new TextResponse<THEDAILYWTFFORUM>();

    Response.Write(response.GetText());

     

    That's my generic response to this thread. I have no idea what I said though. Whatever I said is abstracted from the fact that I replied.

     

    See you in the bar,

    Ribbly Screwspigot

  • Ribbly Screwspigot (unregistered) in reply to Ribbly Screwspigot
    Anonymous:

    TextResponse<THEDAILYWTFFORUM> response = new TextResponse<THEDAILYWTFFORUM>();

    Response.Write(response.GetText());

     

    That's my generic response to this thread. I have no idea what I said though. Whatever I said is abstracted from the fact that I replied.

     

    See you in the bar,

    Ribbly Screwspigot

     

    Darn you, FreeTextBox.

    TextResponse<THEDAILYWTFFORUM> response = new TextResponse<THEDAILYWTFFORUM>();

    Response.Write(response.GetText());

     

  • (cs) in reply to paula

    Anonymous:
    So what's worse...generic databases, or generic types?

    Generic data stored as CDATA sections in an XML database :)

  • (cs) in reply to biziclop

    biziclop:
    Athas:
    Anonymous:
    Generics may sound great but really they are a dirty hack that does not actually provide any type saftey at all.

    List<INTEGER> myList = new ArrayList<INTEGER>();
    List list2 = myList;
    list2.add(new String());

    Code compiles, now iterate through your genericized myList and see what happens.


    If this really does as you say, then it would, in my opinion, be a defect in the implementation of generic programming in C#. C++ would not accept such nonsense. You do not want a supposedly modern, managed language to be less safe than a volcano language like C++. Why aren't the template/generic/type parameters for list2 inferred from the type definition of myList? It should be blindingly obvious to the compiler! And why does C# allow a generic class to be instantiated without proper template/generic/type parameters? Does the compiler at least emit a warning? What's the point of a static language if the compiler doesn't perform bondage-style static checks? Why not just use a fully dynamic language then?
    </INTEGER></INTEGER>


    Let's face it: inheritance and generics don't go well together.
    The only case when they do is when a language is specifically designed to have both. These languages are very strongly type-safe, don't have a father-of-all Object class, class inheritance graphs are not trees but generic forests and all interaction between these two ways of generalization is strictly regulated.

    If you have both Object and generics, no matter how clever the implementation is, anomalies will occur.
    Just for the sake of illustration: If A extends B, does C extend C?
    If it does, you can cast your Collection<STRING> to Collection<COMPARABLE> and put a nasty non-String in it. (See the quoted code, provided it really works in C#.)
    If it doesn't, you're in all kinds of mess. How do you implement a sort() function for your Collection<COMPARABLE>? One thing is sure: it won't work for your Collection<STRING>. Eventually you are forced to juggle a bit with the structure of your code. I don't really know how other languages tried to cope with this, Java tried to solve this by using bounded wildcard types. Of course, this method has it's own drawbacks, again forcing you into some weird hacks. (And the less talented you are, the weirder those hacks will be. :))

    All this in the name of clarity and readability.
    Tthe third "advantage", compile-time type safety sounds ok. It's just I've never encountered a single bug caused by putting the wrong type of object into a container, despite having seen (and having been forced to maintain) vast loads of crap code over the year.
    A complicated solution for a non-existent problem, if you ask me.

    With some of these responses, I have to wonder if any of these people questioning the utility of generics has really done much object-oriented coding in the real world.  If you've ever hand-coded a strongly typed version of a collection where you just wrapped all the "generic" methods of the superclass in a more specifically typed version of the sub-class, then surely you can see the benefits of generics.  I haven't seen one problem mentioned that didn't exist before generics nor have I seen an example of a problem caused specifically by generics.   If you don't like compile-time type checking, then declare everything an object and quit bitching.  If you don't like generics, don't use them.

  • (cs) in reply to Judah
    Anonymous:
    Anonymous:
    zip:

    Anonymous:
    So given that C++ has no basic Object class...
    what was this guy doing in C++?

    Void pointers, baby!  Woohoo!


    My brane just exploded.

    Meh bane jut splode

    <FONT face="Courier New">YOUR HEAD ASPLODE</FONT>

    (With apologies to Strongbad.)

  • (cs) in reply to JohnO
    JohnO:
    With some of these responses, I have to wonder if any of these people questioning the utility of generics has really done much object-oriented coding in the real world.  If you've ever hand-coded a strongly typed version of a collection where you just wrapped all the "generic" methods of the superclass in a more specifically typed version of the sub-class, then surely you can see the benefits of generics.  I haven't seen one problem mentioned that didn't exist before generics nor have I seen an example of a problem caused specifically by generics.   If you don't like compile-time type checking, then declare everything an object and quit bitching.  If you don't like generics, don't use them.


    It is a very tiny fraction of programmers who actually understand OO.  Most just subclass the shit out of everything and tell themselves and their superiors that it's OO.
  • (cs) in reply to brazzy
    brazzy:
    I think you are confusing the completely separate issues of static/dynamic and strong/weak typing. Java has strong static typing


    I have reused the terminology of the original poster. The misuse of dynamic instead of strong is quite common. So yes I favor strong static programming languages (but I was lucky to work on a big project in Lisp for many years). And while I have used Java for the last decade, its type system is far from perfect.
  • (cs) in reply to trollable
    trollable:
    brazzy:
    I think you are confusing the completely separate issues of static/dynamic and strong/weak typing. Java has strong static typing


    I have reused the terminology of the original poster. The misuse of dynamic instead of strong is quite common. So yes I favor strong static programming languages (but I was lucky to work on a big project in Lisp for many years). And while I have used Java for the last decade, its type system is far from perfect.


    As for me, I do know the difference between dynamic typing and weak typing and I really meant I prefer dynamic. Preferably strong, too, but I'm not too picky about it.

    Java is a hybrid. Its type system is not truly static - I like that - but it's excessively strong, which mostly hampers programming, thereby forcing programmers to devise unsafe workarounds. Which, in turn, would be caught by a good static type system. Which, as I said, Java doesn't have...

    Bleah.

  • (cs) in reply to Anonymouse
    Anonymouse:
    Athas:
    Anonymous:
    Generics may sound great but really they are a dirty hack that does not actually provide any type saftey at all.

    List<integer> myList = new ArrayList<integer>();
    List list2 = myList;
    list2.add(new String());

    Code compiles, now iterate through your genericized myList and see what happens.


    If this really does as you say, then it would, in my opinion, be a defect in the implementation of generic programming in C#. C++ would not accept such nonsense. You do not want a supposedly modern, managed language to be less safe than a volcano language like C++. Why aren't the template/generic/type parameters for list2 inferred from the type definition of myList? It should be blindingly obvious to the compiler!</integer></integer>


    Obvious? Oh really? how about

    List intList<int> = new ArrayList<int>();
    List stringList<string> = new ArrayList<string>();
    List list2;
    Random rnd = new Random();
    if (rnd.NextDouble() <= 0.5) {
       list2 = intList;
    } else {
       list2 = stringList;
    }
    list2.add(new String());

    Not so obvious now, eh?


    This is, without a doubt, the single funniest in-code counter example I have ever seen.

       -dave-
    </string></string></int></int>
  • (cs) in reply to biziclop

    biziclop:
    If you have both Object and generics, no matter how clever the implementation is, anomalies will occur.
    Just for the sake of illustration: If A extends B, does C[A] extend C[B]?
    If it does, you can cast your Collection<STRING> to Collection<COMPARABLE> and put a nasty non-String in it. (See the quoted code, provided it really works in C#.)
    If it doesn't, you're in all kinds of mess. How do you implement a sort() function for your Collection<COMPARABLE>? One thing is sure: it won't work for your Collection<STRING>. Eventually you are forced to juggle a bit with the structure of your code. I don't really know how other languages tried to cope with this, Java tried to solve this by using bounded wildcard types. Of course, this method has it's own drawbacks, again forcing you into some weird hacks. (And the less talented you are, the weirder those hacks will be. :))

    C[A] must not extend C[B]. this is the entire reason generics exist - we could not create a StringList interface which extended List and obeyed the Liskov substitution principle. Java dealt with the sort() function on collections via: List[T implements Comparable] so that you could make a library function work to sort both on List[String] and List[Date] or any later implementation of Comparable. The problem comes from making the generic collections assignable to the raw collection - bringing back the equivalent of the ArrayStoreException which happend when you did Object[] foo = new String[5]. The designers tell us they can't make it an error because of backwards compatibility so they just do a warning. The know-it-alls on this forum tell us we must never ignore warnings and treat them as errors if we want type-safety.

    So what this means is you cannot have type safety and backwards compatibility. Since we need backwards compatibility, we lose type safety. And the point of entire point of generics is.... type safety. I think I'll just go play HitchHiker's guide and grab some tea and no tea.

     

  • (cs) in reply to OneFactor
    OneFactor:
    So what this means is you cannot have type safety and backwards compatibility. Since we need backwards compatibility, we lose type safety. And the point of entire point of generics is.... type safety. I think I'll just go play HitchHiker's guide and grab some tea and no tea.


    What's so unusual about a conflict of objectives? Or about this particular one? You do not always need backwards compatibility, and in that case you can have "real" type safety by eliminating all generics warnings. In most other cases, you need backwards compatibility only in those places where you interface with pre-generics APIs and still get the benefit for the rest of the app.
  • (cs) in reply to JohnO
    JohnO:

    With some of these responses, I have to wonder if any of these people questioning the utility of generics has really done much object-oriented coding in the real world.  If you've ever hand-coded a strongly typed version of a collection where you just wrapped all the "generic" methods of the superclass in a more specifically typed version of the sub-class, then surely you can see the benefits of generics.  I haven't seen one problem mentioned that didn't exist before generics nor have I seen an example of a problem caused specifically by generics.   If you don't like compile-time type checking, then declare everything an object and quit bitching.  If you don't like generics, don't use them.



    For a start, I personally don't like logically contradicting structures, language elements just "hacked in" without providing a strong threoretic foundation first. If you take away the clarity and unambiguity of the JLS you can just as well use C++. But this is just my built-in distrust.

    On the other hand it's fairly typical not to understand the maintainers' point of view. A coder can easily say "don't use'em if you don't like'em", a maintainer's life is not that simple.

    I've done OOP coding in the real world and this is why I know that having a class that's only a collection of other classes is definitely bad design. (And definitely not OOP.)

    And the problem caused by generics should be quite obvious: one more way for to wreak havoc and one more excuse for bad design.
    No big deal really, no more whining from me, if we've lived through J2EE, we can cope with this generics guy. :)

Leave a comment on “Generic Generics”

Log In or post as a guest

Replying to comment #:

« Return to Article