泛型

一,什么是泛型
1.这是一个Int类型的集合
public class IntList
    {
        int[] arr;
        int count;

        /// <summary>
        /// 获取已储存的元素的个数
        /// </summary>
        public int Count
        {
            get { return count; }
        }

        public IntList(int length)
        {
            arr = new int[length];
        }

        #region 1.0 向集合中 追加元素 +void Add(int ele)
        /// <summary>
        /// 向集合中 追加元素
        /// </summary>
        /// <param name="ele"></param>
        public void Add(int ele)
        {
            //判断当前已添加元素的个数 是否 大于 数组的容量
            if (count >= arr.Length)
            {
                //创建 2倍 的新数组
                int[] arrNew = new int[arr.Length * 2];
                //将arr 里的 数据 复制到 新数组中(从新数组的第0个位置开始存放)
                arr.CopyTo(arrNew, 0);
                //将新数组的引用 设置给 arr
                arr = arrNew;
            }
            //将元素 加入到 数组中
            arr[count] = ele;
            //元素总个数 +1
            count++;
        } 
        #endregion

        #region 2.0 索引器  +int this[int index]
        public int this[int index]
        {
            get
            {
                if (index >= arr.Length)
                {
                    throw new System.Exception("数组下标越界!");
                }
                else
                {
                    return arr[index];
                }
            }

            set
            {
                if (index >= arr.Length)
                {
                    throw new System.Exception("数组下标越界!");
                }
                else
                {
                    arr[index] = value;
                }
            }
        } 
        #endregion

2.这是一个String类型集合
public class StringList
    {
        string[] arr;
        int count;

        /// <summary>
        /// 获取已储存的元素的个数
        /// </summary>
        public int Count
        {
            get { return count; }
        }

        public StringList(int length)
        {
            arr = new string[length];
        }

        #region 1.0 向集合中 追加元素 +void Add(int ele)
        /// <summary>
        /// 向集合中 追加元素
        /// </summary>
        /// <param name="ele"></param>
        public void Add(string ele)
        {
            //判断当前已添加元素的个数 是否 大于 数组的容量
            if (count >= arr.Length)
            {
                //创建 2倍 的新数组
                string[] arrNew = new string[arr.Length * 2];
                //将arr 里的 数据 复制到 新数组中(从新数组的第0个位置开始存放)
                arr.CopyTo(arrNew, 0);
                //将新数组的引用 设置给 arr
                arr = arrNew;
            }
            //将元素 加入到 数组中
            arr[count] = ele;
            //元素总个数 +1
            count++;
        } 
        #endregion

        #region 2.0 索引器  +int this[int index]
        public string this[int index]
        {
            get
            {
                if (index >= arr.Length)
                {
                    throw new System.Exception("数组下标越界!");
                }
                else
                {
                    return arr[index];
                }
            }

            set
            {
                if (index >= arr.Length)
                {
                    throw new System.Exception("数组下标越界!");
                }
                else
                {
                    arr[index] = value;
                }
            }
        } 
        #endregion
当我们操作这些集合的时候
IntList intList = new IntList(3);
            intList.Add(9);
            intList.Add(19);
            intList.Add(59);

            for (int i = 0; i < intList.Count; i++)
            {
                Console.WriteLine(intList[i]);
            }

            StringList stringList = new StringList(3);
            stringList.Add("9a");
            stringList.Add("19b");
            stringList.Add("59c");

            for (int i = 0; i < stringList.Count; i++)
            {
                Console.WriteLine(stringList[i]);
            }

会发现变得只是类型,这样重复的类型变换有什么办法解决了,这就需要用到泛型

/// <summary>
    /// 自定义泛型集合类,带泛型参数
    /// </summary>
    /// <typeparam name="MyType">集合的元素类型</typeparam>
    public class MyGenericList<MyType>
{
        MyType aValue;
        MyType[] arr;
        int count;
        //int a = MyType;

        #region 获取已储存的元素的个数 +int Count
        /// <summary>
        /// 获取已储存的元素的个数
        /// </summary>
        public int Count
        {
            get { return count; }
        } 
        #endregion

        public MyGenericList(int length)
        {
            arr = new MyType[length];
        }

        #region 1.0 向集合中 追加元素 +void Add(MyType ele)
        /// <summary>
        /// 向集合中 追加元素
        /// </summary>
        /// <param name="ele"></param>
        public void Add(MyType ele)
        {
            //判断当前已添加元素的个数 是否 大于 数组的容量
            if (count >= arr.Length)
            {
                //创建 2倍 的新数组
                MyType[] arrNew = new MyType[arr.Length * 2];
                //将arr 里的 数据 复制到 新数组中(从新数组的第0个位置开始存放)
                arr.CopyTo(arrNew, 0);
                //将新数组的引用 设置给 arr
                arr = arrNew;
            }
            //将元素 加入到 数组中
            arr[count] = ele;
            //元素总个数 +1
            count++;
        } 
        #endregion

        #region 2.0 索引器  +MyType this[int index]
        public MyType this[int index]
        {
            get
            {
                if (index >= arr.Length)
                {
                    throw new System.Exception("数组下标越界!");
                }
                else
                {
                    return arr[index];
                }
            }

            set
            {
                if (index >= arr.Length)
                {
                    throw new System.Exception("数组下标越界!");
                }
                else
                {
                    arr[index] = value;
                }
            }
        } 
        #endregion
现在调用则可以变成
MyGenericList<int> intList = new MyGenericList<int>(3);
            intList.Add(9);
            intList.Add(19);
            intList.Add(59);

            for (int i = 0; i < intList.Count; i++)
            {
                Console.WriteLine(intList[i]);
            }
string 类型的则可以
  MyGenericList<string> stringList = new MyGenericList<string>(3);
            stringList.Add("9a");
            stringList.Add("19b");
            stringList.Add("59c");

            for (int i = 0; i < stringList.Count; i++)
            {
                Console.WriteLine(stringList[i]);
            }
MyType只是相当于一个占位符,用的时候用具体的类型来替换即可。他只能是一个类型,不能是具体的值。
泛型是指的带类型参数的类,而不是类型参数本身。如public class MyList<T>{….}其中的MyList就是泛型,而T是类型参数。
泛型参数可以有多个,比如MyList<T,MyType>也是可以的
实例化一个引用类型的泛型,它在内存中分配的大小是一样的。
实例化一个值类型的泛型,它在内存中分配的大小是不一样的。
尽管如此,CLR还是为每个不同的类型参数创建了不同的泛型类版本。       

二.泛型的继承

继承一个泛型类时,必须为其传递泛型参数!

public class Father<k,v>{}//父类

定义子类时直接为父类泛型参数赋值
public class Son:Father<int,string>
 
定义子类时把子类泛型参数赋给父类泛型参数
public  class Son<w,y>:Father<int,string>
 
public  class Son:Father<k,v>
这种是错误的,因为K,V不存在
 
三.泛型约束
 public class MyGenericDog<T> 
        where T:new()//约束 传给 T 的类 必须包含一个 无参的构造函数
    {
        T t;
        public MyGenericDog()
        {
            t = new T();
        }
}

在使用时必须保证类有一个无参的构造函数

 private void btnNewT_Click(object sender, EventArgs e)
        {
            MyGenericDog<LittleDog> list = new MyGenericDog<LittleDog>();
        }
public class LittleDog
    {
        public LittleDog()
        {
        }

        public LittleDog(string str)
        {
        }
  }

四.用来约束泛型参数 必须是某个类 或者某个类的子类

class Dog
{
    public void Shout(){}
}
class Cat
{
    public void Walk(){}
}
class House<TPet,TPet2>where TPet:Dog where TPet2:Cat
{
    public c(TPet p,TPet2 p2)
   {
       p1.Shout();
       p2.Walk();
   }
}

1.一个泛型参数不允许多个基类约束,不能写成

class House<TPet,TPet2>where TPet:Dog where TPet:Cat
因为不可能既是狗,又是猫。
2.不能为密封类指定基类约束(string) 密封类即为私有类。即sealed这种不能继承的类。
3.也不能用nullable<T>
五.用来约束泛型参数必须是值类型或者引用类型
public struct A{}
public class B{}
public class C<T> where T:struct  值类型
{
}
public class C2<T> where T:class  引用类型
{
}

比如上面的如果使用c<person>就会报错
六.泛型方法
public void Test<k>() where k:new()
{
}

K可以用在三个地方:

1.参数

public void Test<k>(k a) {
}

2.可以在方法体内用到

public void Test<k>() where k:new()
{
   k k1=new k();
}

3.可以当返回值

public K Test<k>() where k:new()
{
   return k;
}

七.泛型方法的重载

void sayA()
            {
            }
           void sayA<T>()
            {
            }
           void sayA<K>()
            {
            }

在使用时可以看到智能提示出现两个方法say,say<>说明他们不构成重载

           void sayA<T>()
            {
            }
           void sayA<K>()
            {
            }
这样是不行的,因为泛型方法只是个占位符,编译器会认为是同一个方法

八.泛型方法重写

6@%9ZGPL460]WM}N3PO5T3O

子类当中约束where k:class是不能在子类中重写。而where k:new()不需要些,从父类中继承过来了。

原文地址:https://www.cnblogs.com/automation/p/3416393.html