views:

84

answers:

5

In the chapter Generics CLR Via C# v3, Jeffrey Richter says below TypeList<T> has two advantages

  1. Compile-time type safety
  2. boxing value types

over List<Object>, but how is the Compile-time type safety is achieved?

//A single instance of TypeList could hold different types.
using System;
using System.Collections.Generic;
using System.Text;
namespace MyNamespace 
{
    namespace Generics
    {
        class Node
        {
            private Node next_;

            public Node(Node next) {
                next_ = next;        
            }

            public Node getNext() {
                return next_;
            }
        }
        internal sealed class TypeList<T> :Node
        {
            T data_;
            public T getData() {
                return data_;
            }

            public TypeList(T data, Node next):base(next) {
                data_ = data;
            }

            public TypeList(T data):this(data,null) {


            }
            public override String ToString()
            {
                return data_.ToString() + (base.getNext() != null ? base.getNext().ToString() : string.Empty);
            }

          }
        class Dummmy:Object
        {
            public override String ToString() {
               return "Dummytype".ToString();

            }

        }

        class Program
        {
            static void Main(string[] args)
            {
                Dummmy dummy = new Dummmy();
                Node list = new TypeList<int>(12);
                list = new TypeList<Double>(12.5121, list);
                list = new TypeList<Dummmy>(dummy, list);
                Double a = ((TypeList<Double>)list).getData();//Fails at runTime invalid cast exception
                Console.WriteLine(list.ToString());
                Console.Write("sds");
            }
        }
    }

}
+5  A: 

Compile type safety means that you will get all errors about invalid type usage at compile time but not at runtime.

For example following code would cause compile time error:

TypeList<int> list = new TypeList<int>(1);
string someString = list.getData(); // compile error here

And if you used TypeList<object> there would be no compile time safety because compiler won't report an error and you would get runtime error:

TypeList<object> list = new TypeList<object>(1);
string someString = (string)list.getData(); // runtime error here
Andrew Bezzub
@Andrew A single instance of TypeList could hold different types. That is the reason for going for TypeList<T> than some timing that can hold a single type.
yesraaj
@yesraaj: Signle instance of TypeList<T> can hold only value of type T which is specified at compile time.
Andrew Bezzub
Please look at the sample code in main block in the code snippet that I have in question.
yesraaj
@yesraaj:In your sample different instances of TypeList<T> hold different types. And when you trying to extract value of the wrong type exception occurs.
Andrew Bezzub
+1  A: 

It means that because TypeList is a generic class, it is known at compile time what is the type used which avoids you the need to cast at runtime to the actual type being used.

Darin Dimitrov
+1  A: 

Since TypeList is generic. The actual type of T is defined at compile time so any checking with the type is done at compile time.

Arseny
A: 

This document, Design and Implementation of Generics for the .NET Common Language Runtime, goes into detail about generics, and the trade-offs that were made to implement them.

Douglas
+1  A: 
 Double a = ((TypeList<Double>)list).getData();  //Fails at runTime

This is the crux of your question. The list variable is actually a TypeList<Dummy>. The compiler knows that and it generated a compile time error when you wrote

 Double a = list.getData();

Compile-time type safety at work there. But you applied a cast to let it compile. The compiler works from he assumption: "he knows what he's doing, he used a cast" and lets it pass. Won't work of course, now it bombs at runtime.

You could argue "but the compiler knows that the cast can't work, isn't that what type safety is all about?". Nope, a cast is very powerful, it let's you override what the compiler knows. This particular example isn't a very good one, but you have to use a cast to convert a base class reference to a derived class reference for example. Fairly common. The power of a cast is what makes it dangerous. The big advantage of generics is that you don't need to use them.

Hans Passant
@Hans list.getData() // Compiler error because list doesn't have a getData method
yesraaj
@yesraaj - your TypeList<> *does* have a getData() member, not sure what you mean.
Hans Passant
list is of type List and Not TypeList<>.
yesraaj
@yesraaj - what makes you think that? Your code says `list = new TypeList<Dummmy>(dummy, list);`
Hans Passant
@Hans Passant you are right
yesraaj