欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#泛型实例详解

程序员文章站 2024-02-15 09:16:58
本文以实例形式讲述了c#泛型的用法,有助于读者深入理解c#泛型的原理,具体分析如下: 首先需要明白什么时候使用泛型: 当针对不同的数据类型,采用相似的逻辑算法,为了避免...

本文以实例形式讲述了c#泛型的用法,有助于读者深入理解c#泛型的原理,具体分析如下:

首先需要明白什么时候使用泛型:

当针对不同的数据类型,采用相似的逻辑算法,为了避免重复,可以考虑使用泛型。

一、针对类的泛型

针对不同类型的数组,写一个针对数组的"冒泡排序"。

1.思路

● 针对类的泛型,泛型打在类旁。
● 由于在"冒泡排序"中需要对元素进行比较,所以泛型要约束成实现icomparable接口。

  class program
  {
    static void main(string[] args)
    {
      sorthelper<int> isorter = new sorthelper<int>();
      int[] iarray = {8, 7, 1, 2, 12};
      isorter.bubblesort(iarray);
      foreach (int item in iarray)
      {
        console.write(item+ ", ");
      }
      console.readkey();
    }
  }
 
  public class sorthelper<t> where t : icomparable
  {
    public void bubblesort(t[] array) 
    {
      int length = array.length;
      for (int i = 0; i <= length -2; i++)
      {
        for (int j = length - 1; j >= 1; j--)
        {
          if (array[j].compareto(array[j-1]) < 0)
          {
            t temp = array[j];
            array[j] = array[j - 1];
            array[j - 1] = temp;
          }
        }
      }
    }
  }
 

运行结果如下图所示:

C#泛型实例详解

2.关于泛型约束

where t : icomparable 把t约束为实现icomparable接口
where t : class
where t : struct
where t : icomparable, new() 约束泛型必须有构造函数

3.关于冒泡算法

● 之所以for (int i = 0; i <= length -2; i++),这是边界思维,比如有一个长度为5的数组,如果0号位元素最终调换到4号位,每次调一个位,需要经过4次才能到4号位,即for(int i = 0; i <= 5-2, i++),i依次为0, 1, 2, 4,期间经历了4次。

● 至于for (int j = length - 1; j >= 1; j--)循环,即遍历从最后一个元素开始到索引为1的元素,每次与前一个位置上的元素比较。

4.关于比较

int类型之所以能比较,是因为int类型也实现了icomparable接口。

C#泛型实例详解

byte类型也一样实现了icomparable接口。

C#泛型实例详解

二、自定义一个类,使之也能实现冒泡算法

冒泡算法涉及到元素比较,所以自定义类必须实现icomparable接口。

  class program
  {
    static void main(string[] args)
    {
      book[] bookarray = new book[2];
      book book1 = new book(100, "书一");
      book book2 = new book(80, "书二");
      bookarray[0] = book1;
      bookarray[1] = book2;
 
      console.writeline("冒泡之前:");
      foreach (book b in bookarray)
      {
        console.writeline("书名:{0},价格:{1}", b.title, b.price);
      }
 
      sorthelper<book> sorter = new sorthelper<book>();
      sorter.bubblesort(bookarray);
      console.writeline("冒泡之后:");
      foreach (book b in bookarray)
      {
        console.writeline("书名:{0},价格:{1}", b.title, b.price);
      }
      console.readkey();
    }
  }
 
  public class sorthelper<t> where t : icomparable
  {
    public void bubblesort(t[] array) 
    {
      int length = array.length;
      for (int i = 0; i <= length -2; i++)
      {
        for (int j = length - 1; j >= 1; j--)
        {
          if (array[j].compareto(array[j-1]) < 0)
          {
            t temp = array[j];
            array[j] = array[j - 1];
            array[j - 1] = temp;
          }
        }
      }
    }
  }
 
  //自定义类实现icomparable接口
  public class book : icomparable
  {
    private int price;
    private string title;
 
    public book(){}
 
    public book(int price, string title)
    {
      this.price = price;
      this.title = title;
    }
 
    public int price
    {
      get { return this.price; }
    }
 
    public string title
    {
      get { return this.title; }
    }
 
    public int compareto(object obj)
    {
      book book = (book)obj;
      return this.price.compareto(book.price);
    }
  }

运行结果如下图所示:

C#泛型实例详解

三、针对方法的泛型

继续上面的例子,自定义一个类,并定义泛型方法。

  //方法泛型
  public class methodsorthelper
  {
    public void bubblesort<t>(t[] array) where t : icomparable
    {
      int length = array.length;
      for (int i = 0; i <= length - 2; i++)
      {
        for (int j = length - 1; j >= 1; j--)
        {
          if (array[j].compareto(array[j - 1]) < 0)
          {
            t temp = array[j];
            array[j] = array[j - 1];
            array[j - 1] = temp;
          }
        }
      }
    }
  }
 

主程序如下:

  class program
  {
    static void main(string[] args)
    {
      book[] bookarray = new book[2];
      book book1 = new book(100, "书一");
      book book2 = new book(80, "书二");
      bookarray[0] = book1;
      bookarray[1] = book2;
 
      console.writeline("冒泡之前:");
      foreach (book b in bookarray)
      {
        console.writeline("书名:{0},价格:{1}", b.title, b.price);
      }
 
      methodsorthelper sorter = new methodsorthelper();
      sorter.bubblesort<book>(bookarray);
      console.writeline("冒泡之后:");
      foreach (book b in bookarray)
      {
        console.writeline("书名:{0},价格:{1}", b.title, b.price);
      }
      console.readkey();
    }
  }  
 

运行结果如下图所示:

C#泛型实例详解

另外,使用泛型方法的时候,除了按以下:

methodsorthelper sorter = new methodsorthelper(); 
sorter.bubblesort<book>(bookarray);

还可以这样写:  

      methodsorthelper sorter = new methodsorthelper(); 
      sorter.bubblesort(bookarray); 
     

可见,泛型方法可以根据数组实例隐式推断泛型是否满足条件。

四、泛型的其它优点

1.避免隐式装箱和拆箱

以下包含隐式装箱和拆箱:

arraylist list = new arraylist();
for(int i = 0; i < 3; i++)
{
  list.add(i); //add接收的参数类型是引用类型object,这里包含了隐式装箱
}
for(int i = 0; i < 3; i++)
{
  int value = (int)list[i]; //引用类型强转成值类型,拆箱
  console.writeline(value);
}

使用泛型避免隐式装箱和拆箱:

list<int> list = new list<int>();
for(int i = 0; i < 3; i++)
{
  list.add(i);
}
for(int i = 0; i < 3; i++)
{
  int value = list[i];
  console.writeline(value);
}

2.能在编译期间及时发现错误

不使用泛型,在编译期不会报错的一个例子:

arraylist list = new arraylist();
int i = 100;
list.add(i);
string value = (string)list[0];

使用泛型,在编译期及时发现错误:

list<int> list = new list<int>();
int i = 100;
list.add(i);
string value = (string)list[0];

五、使用泛型的技巧

1.在当前文件中给泛型取别名

using intlist = list<int>;
intlist list = new intlist();
list.add(1);

2.在不同文件中使用泛型别名,定义一个类派生于泛型

public class intlist : list<int>{}