C#-泛型

一、概念

  • 泛型实现了类型参数化,达到代码复用的目的

  • 通过类型参数化来实现同一份代码上操作多种类型

  • 泛型相当于类型占位符

  • 定义类或方法时使用替代符代表变量类型

  • 当真正使用类或者方法时再具体指定类型

泛型的本质是类型参数化或参数化类型,在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型。

也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。

二、泛型类和泛型接口

1.泛型类声明

calss 类名<泛型占位字母>

class TestClass<T>//泛型类
{
    public T value;
}


TestClass<int> t1 = new TestClass<int>();
TestClass<string> t2 = new TestClass<string>();

class TestClass2<T1,T2,T3,T4>//泛型类多个参数
{
    public T1 value1;
    public T2 value2;
    public T3 value3;
    public T4 value4;
}
TestClass2<int,string,bool,float> t3= newTestClass2<int,string,bool,float>()

2.泛型接口声明

interface 接口名<泛型站位字母>

interface TestInterface<T>//泛型接口
{
    T VAlue
    {
        get;
        set;
    }
}
class Test:TestInterface<int>
{
//继承时也需填写
}

三、泛型方法

声明

函数名<泛型占位字母>(参数列表)

注意:泛型占位字母可以有多个,用逗号分开

  1. 普通类中的泛型方法

Class Test{
    public H Test<H>( H v)
    {
        return v ;//H为 可变类型 使用时指定类型
    }

    public void Test<T>()
    {
        T t =default(T);//默认值,可做逻辑处理
    }

    public void Test<T1,T2,T3>(T1 t1,T2 t2,T3 t3)
    {
       //可做多个泛型占位符
    }
}

2.泛型类中的泛型方法

class Test<T>
{
    //T类型的成员变量 当使用该类时 value的类型才被确定
    //声明泛型时T也可以换成任何字母(一般用大写)
    public T value;
    
    //不是泛型方法
    //使用泛型类中的可变类型 作为参数和返回值的
    public T Test(T t)
    {
        return t;
    }
    
    //泛型方法 K为可变类型使用时为指定类型
    public K Test<K>( K v)
    {
        return v;
    }        
}

四、泛型约束

1.概念

限制泛型的类型

关键字:where

2.泛型约束类型

泛型约束一共有6种

where 泛型字母:约束类型

  1. 值类型 where 泛型字母:struct

  1. 引用类型 where 泛型字母:class

  1. 存在无参公共构造函数 where 泛型字母:new()

  1. 某个类本身或其派生类 where 泛型字母:类名

  1. 某个接口的派生类型 where 泛型字母:接口名

  1. 另一个泛型类型本身或者派生类型 where 泛型字母:另一个泛型字母

  1. 值类型约束

public class Test<T> where T: struct
{
    public T value;
    //泛型方法加上值约束代表K只能使用值类型
    public void TestFun<K>() where K: struct
    {
    }
}

//使用时只能使用值类型
Test<int> t = new Test<int>();
t.value = 100;
t.TestFun<float>();

  1. 引用类型约束

public class Test<T> where T: class
{
    public T value;
    //泛型方法加上值约束代表K只能使用引用类型
    public void TestFun<K>() where K: class
    {
    }
}

//使用时 只能使用引用类型
Test<string> t = new Test<string>();
t.value = "123";
t.TestFun<string>();

  1. 公共无参构造约束

public class Test<T> where T: new()
{
    public T value;
    //泛型方法  加上无参约束  代表K类型必须存在无参构造
    public void TestFun<K>() where K:new()
    {
    }
}

public class Test1
{
}

public class Test2
{
    public Test2(int a)
    {
    }
}

//使用时 只能使用含有  无参构造函数的类型
Test<Test1> t = new Test<Test1>();
t.TestFun<Test1>();

  1. 类约束

public class Test<T> where T:Test1
{
    public T value;
    //泛型方法  加上某个类名作为约束  代表K类型必须为该类或者其派生类
    public void TestFun<K>() where K:Test1
    {
    }
}
public class Test1...
public class Test2 : Test1
{
}
public class Test3...

//使用时  只能使用该类或其派生类
Test<Test1> t = new Test<Test1>();
t.TestFun<Test2>();

5.接口约束

public class Test<T> where T : ITest
{
    public T value;
    //泛型方法  加上某个接口名作为约束  代表T类型必须该接口或者其派生类型
    public void TestFun<K>() where K : ITest
    {
    }
}
public interface Itest...
//继承接口的类
public class Test1 : ITest
{
}
//继承接口的接口
public interface ITest2:Itest
{
}
//没有继承接口
public class Test2...

//使用时  只能使用改接口或者该接口的派生类型
Test<Test1> tt = new Test<Test1>();
t.TestFun<ITest2>();

6.另一个类型约束

public class Test<T,U> where T : U
    public T value;
    //泛型方法  加上另一个泛型占位符作为约束  K表示必须和L是同一类型或者其派生类型
    public void TestFun<K,L>() where K : L
    {
    }
}
public interface ITest...
//继承接口的类
public class Test1: ITest
{
}
public class Test2...
//使用时  只能使用改接口或者其派生类型
Test<Test1,ITest> t = new Test<Test1,Itest>();
t.TestFun<Test1,Test1>();

3.约束的组合使用

泛型类  多个约束组合使用,用逗号分割 如果不能组合使用会报错
public class Test<T> where T: class , new()
{
public T value;
//泛型方法多个约束组合使用用逗号分隔如果不能组合使用会报错l 
public void TestFun<K>( ) where K: ITest, new()
{

}
}
public interface ITest...

4.多个泛型有约束

public class Test<T,H> where T:class,new( ) where H:struct
{
public T value;
//泛型方法多个泛型都有约束用多个where拼接
public void TestFun<K,L>() where K: ITest,new( ) where L:class
{
}
}
public interface ITest. . .

注意:
//当使用泛型作为函数返回值时
public K TestFun<K>()
{
//当没有约束时不确定泛型类型时值还是引用
//可以使用default关键字得到泛型类型作为对象时的默认值返回
//—般情况下  引用为null 值为0
return default(K);
}

五、泛型作用

1.不同类型对象的相同逻辑处理可以选择泛型

2.使用泛型可以一定程度避免装箱拆箱

举例:优化ArrayList

class ArrayList<T>
{
    private T[] array;
    //增删查改
    public void Add(T value)
    {
    }
}

六、总结

1.泛型类接口方法

声明语法

泛型类

class 类名<占位字母>

泛型接口

interface 接口名<泛型站位字母>

泛型方法

返回值类型 函数名<占位字母>(参数类型 参数...)

概念

  • 泛型相当于类型占位符

  • 占位字母可以有多个

  • 占位字母一般为大写字母

  • 定义类或方法时使用替代符代表变量类型

  • 当真正使用类或者方法时再具体指定类型

2.泛型约束

约束语法

关键词:where

  • 值类型

where T:struct

  • 引用类型

where T:class

  • 必须存在无参公共构造函数

where T:new()

  • 某个类的派生类

where T:类名

  • 某个接口的派生类型

where T:接口名

  • 另一个泛型的派生类型

where T:U

作用

  • 使用泛型指定类型时

  • 有一定的规则

注意

  • 部分约束可以组合使用

  • 多个约束用逗号隔开

  • 多个泛型都有约束

  • 用多个where

补充

  • 泛型对象默认值

  • default(泛型占位符)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值