What is meant by Compile-time typesafety here?
In the chapter Gene开发者_JAVA技巧rics CLR Via C# v3, Jeffrey Richter says below TypeList<T>
has two advantages
- Compile-time type safety
- 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");
}
}
}
}
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
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.
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.
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.
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.
精彩评论