日期:2014-05-18  浏览次数:20871 次

泛型类继承出现异常
我原来的vs2008快捷键不太对,我又不会设置,于是换了一个vs2008。
然后突然发现我原来运行的项目突然运行不起来了,然后我把报错的原因用一个简单的测试程序写出来了。
请各位帮忙看看。

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
  /// <summary>
  /// 测试的接口
  /// </summary>
  interface I<T>
  {
  T Test(T t);
  }

  /// <summary>
  /// 测试的类
  /// </summary>
  class IT
  {
  public int T;
  }

  /// <summary>
  /// 测试类子类
  /// </summary>
  class ITT : IT
  {
  }

  /// <summary>
  /// 接口实现类
  /// </summary>
  class IT<T> : I<T>
  {
  public T Test(T t)
  {
  return t;
  }
  }

  /// <summary>
  /// 接口实现类
  /// 希望通过传入父类U的一个对象
  /// 能够使用IT子类,也就是上面的那个实现类的方法来处理
  /// </summary>
  class IT_0<T, U> : IT<T>, I<U> where T : class, U
  {
  public U Test(U u)
  {
  T t = u as T;
  if (t != null)
  {
  base.Test(t);
  }
  return u;
  }
  }

  /// <summary>
  /// 固定处理的类是IT类及其子类
  /// IT类在我的程序里是接口
  /// 也就是一个这样的类,可以确定I接口要处理的一个类型及其子类型
  /// </summary>
  class IT_1<T> : IT_0<T, IT> where T : IT
  {
  }

  /// <summary>
  /// 处理IT类
  /// 此时IT_0接口的(T, U)都是IT了
  /// 也就是IT_0类将实现了两次I<IT>接口,且方法的实现不一样
  /// 按常理来说应该子类的方法会覆盖父类的方法的
  /// 可是现在却出现了异常,加载不了IT_2这个类了
  /// </summary>
  class IT_2 : IT_1<IT>
  {
  }

  /// <summary>
  /// 处理IT类的子类型
  /// </summary>
  class IT_3 : IT_1<ITT>
  {
  }

  /*
  * P.S 上面两个类其实可以写成
  * IT_!<IT> it = new IT_1<IT>();
  * IT_1<ITT> itt = new IT_1<ITT>();
  * 但是窗体继承的父类型如果是个泛型类,vs将使用不了可视化编辑界面
  * 所以才会分开写成两个类
  */
  class Program
  {
  static void Main(string[] args)
  {
  IT it = new IT();
  it.T = 100;

  // 没问题
  IT_1<IT> it1 = new IT_1<IT>();
  Console.WriteLine(it1.Test(it).T);

  // 没问题
  IT_3 it3 = new IT_3();
  Console.WriteLine(it3.Test(it).T);

  /* 异常:未能从程序集中加载类型IT_2
  * IT_2继承总结 {}代表类继承的类
  * IT_2 : IT_1<IT>{ IT_0{ IT<IT>{ I<IT> }, I<IT> } }
  * 不难发现,继承到最后,继承了两次 I<IT>,且两个 I<IT> 的实现并不一样
  * 一个是处理 IT 对象,一个是将 IT 对象转换成父类对象再处理
  * 如果是 IT_3 ,则可以将传入的 IT 对象转换成 ITT 后再进行处理,且不会有问题
  */
  IT_2 it2 = new IT_2();
  Console.WriteLine(it2.Test(it).T);


  IT_1<IT> it_2 = new IT_2();
  Console.WriteLine(it_2.Test(it).T);