温度事件的处理器看上去会是:
void boilerSource_NotifyActivity(object info)
{
Temperature value = info as Temperature;
//在使用前downcast需要的类型
}
上面的代码并不直观,且因使用downcast而有些凌乱。借助于泛型,代码将变得更易读且更容易使用。让我们看一下泛型的工作原理:
下面是代理和接口:
public delegate void NotifyDelegate<t>(T info);
public interface ISource<t>
{
event NotifyDelegate<t> NotifyActivity;
}
我们已经参数化了代理和接口。现在的接口的实现中应该能确定这是一种什么类型。
Stock的源代码看上去象这样:
public class StockPriceSource : ISource<double>
{
public event NotifyDelegate<double> NotifyActivity;
//…
}
而Boiler的源代码看上去象这样:
public class BoilerSource : ISource<temperature>
{
public event NotifyDelegate<temperature> NotifyActivity;
//…
}
如果我们各有一个上面每种类的对象,我们将象下面这样来为事件注册一处理器:
StockPriceSource stockSource = new StockPriceSource();
stockSource.NotifyActivity += new NotifyDelegate<double>(stockSource_NotifyActivity);
//这里不必要出现在同一个程序中
BoilerSource boilerSource = new BoilerSource();
boilerSource.NotifyActivity += new NotifyDelegate<temperature>(boilerSource_NotifyActivity);
现在,股票价格的事件处理器会是:
void stockSource_NotifyActivity(double info)
{ //… }
温度的事件处理器是:
void boilerSource_NotifyActivity(Temperature info)
{ //… }
这里的代码没有作downcast并且使用的类型是很清楚的。
12. 泛型与反射
既然泛型是在CLR级上得到支持的,你可以使用反射API来取得关于泛型的信息。如果你是编程的新手,可能有一件事让你疑惑:你必须记住既有你写的泛型类也有在运行时从该泛型类创建的类型。因此,当使用反射API时,你需要另外记住你在使用哪一种类型。我将在例7说明这一点:
例7.在泛型上的反射
public class MyClass<t> { }
class Program
{
static void Main(string args)
{
MyClass<int> obj1 = new MyClass<int>();
MyClass<double> obj2 = new MyClass<double>();
Type type1 = obj1.GetType();
Type type2 = obj2.GetType();
Console.WriteLine("obj1’s Type");
Console.WriteLine(type1.FullName);
Console.WriteLine(type1.GetGenericTypeDefinition().FullName);
Console.WriteLine("obj2’s Type");
Console.WriteLine(type2.FullName);
Console.WriteLine(type2.GetGenericTypeDefinition().FullName);
}
}
在本例中,有一个MyClass<int>的实例,程序中要查询该实例的类名。然后我查询这种类型的GenericTypeDefinition()。GenericTypeDefinition()会返回MyClass<T>的类型元数据。你可以调用IsGenericTypeDefinition来查询是否这是一个泛型类型(象MyClass<T>)或者是否已指定它的类型参数(象MyClass<int>)。同样地,我查询MyClass<double>的实例的元数据。上面的程序输出如下:
obj1’s Type
TestApp.MyClass`1
[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089]]
TestApp.MyClass`1
obj2’s Type
TestApp.MyClass`1
[[System.Double, mscorlib, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089]]
TestApp.MyCl