6.泛型-泛型
6.1 知识点
泛型是什么
泛型实现了类型参数化,达到代码重用的目的。通过类型参数化来实现同一份代码操作多种类型。
泛型相当于类型占位符,定义类或方法时使用替代符代表变量类型,当真正使用类或方法时再具体指定类型。
泛型分类
泛型类:
- 基本语法:
class 类名<泛型占位字母>
- 基本语法:
泛型接口:
- 基本语法:
interface 接口名<泛型占位字母>
- 基本语法:
泛型方法:
- 基本语法:
方法名<泛型占位字母>(参数列表)
- 注意:泛型占位字母可以有多个,用逗号分开。
- 基本语法:
泛型类和泛型接口
在类和接口的语句块外部(namespace语句块内)
泛型类:
单个泛型占位符的泛型测试类:
class SingleGenericClass<T> { public T value; }
多个泛型占位符的泛型测试类:
class MultiGenericClass<T1, T2, K, M, LL, Key, Value> { public T1 value1; public T2 value2; public K value3; public M value4; public LL value5; public Key value6; public Value value7; }
泛型接口:
interface IGenericInterface<T> { T Value { get; set; } }
在主函数内
实例化泛型类:
SingleGenericClass<int> t = new SingleGenericClass<int>(); t.value = 10; Console.WriteLine(t.value); // 输出:10 SingleGenericClass<string> t2 = new SingleGenericClass<string>(); t2.value = "123123"; Console.WriteLine(t2.value); // 输出:123123 MultiGenericClass<int, string, float, double, SingleGenericClass<int>, uint, short> t3 = new MultiGenericClass<int, string, float, double, SingleGenericClass<int>, uint, short>();
泛型方法
在类和接口的语句块外部(namespace语句块内)
普通类中的泛型方法:
class GenericTest2 { public void GenericFunction<T>(T value) { Console.WriteLine(value); } public void GenericFunction<T>() { T t = default(T); } public T GenericFunction<T>(string v) { return default(T); } public void GenericFunction<T, K, M>(T t, K k, M m) { } }
泛型类中的泛型方法:
class GenericTest2<T> { public T value; public void TestFun<K>(K k) { } public void TestFun(T t) { } }
在主函数内
普通类中的泛型方法:
GenericTest2 genericTest2 = new GenericTest2(); genericTest2.GenericFunction<string>("123123"); // 输出:123123
泛型类中的泛型方法:
GenericTest2<int> genericTest_2 = new GenericTest2<int>(); genericTest_2.TestFun(10); // 这不是泛型方法,相当于调用TestFun(int t) genericTest_2.TestFun<string>("123"); // 输出:123 genericTest_2.TestFun<float>(1.2f); // 输出:1.2 genericTest_2.TestFun(true); genericTest_2.TestFun<int>(250); // 这才是泛型方法 genericTest_2.TestFun(250); // 这样用的还是泛型方法
泛型的作用
- 不同类型对象的相同逻辑处理可以选择泛型。
- 使用泛型可以一定程度避免装箱拆箱。
举例:优化 ArrayList
。传入泛型后,不同类型数组可以复用相同的代码。
class ArrayList<T>
{
private T[] array;
public void Add(T value)
{
}
public void Remove(T value)
{
}
}
总结
- 申明泛型时,它只是一个类型的占位符。
- 泛型真正起作用的时候是在使用它的时候。
- 泛型占位字母可以有 n 个,用逗号分开。
- 泛型占位字母一般是大写字母。
- 不确定泛型类型时,获取默认值可以使用
default(占位字符)
。 - 看到
< >
包裹的字母,那肯定是泛型。
6.2 知识点代码
using System;
namespace Lesson5_泛型
{
#region 知识点一 泛型是什么
//泛型实现了类型参数化,达到代码重用目的
//通过类型参数化来实现同一份代码上操作多种类型
//泛型相当于类型占位符
//定义类或方法时使用替代符代表变量类型
//当真正使用类或者方法时再具体指定类型
#endregion
#region 知识点二 泛型分类
//泛型类
//基本语法:class 类名<泛型占位字母>
//泛型接口
//基本语法:interface 接口名<泛型占位字母>
//泛型方法
//基本语法:方法名<泛型占位字母>(参数列表)
//注意:泛型占位字母可以有多个,用逗号分开
#endregion
//class语句块外 namespace语句块内
#region 知识点三 泛型类和泛型接口
//一个泛型占位符的泛型测试类
class SingleGenericClass<T>
{
public T value;
}
//多个泛型占位符的泛型测试类
class MultiGenericClass<T1, T2, K, M, LL, Key, Value>
{
public T1 value1;
public T2 value2;
public K value3;
public M value4;
public LL value5;
public Key value6;
public Value value7;
}
//泛型接口
interface IGenericInterface<T>
{
T Value
{
get;
set;
}
}
//继承泛型接口的类 继承的时候要传入实际的类型
class GenericTest : IGenericInterface<int>
{
//里面的变量会变成传入的实际类型
public int Value { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
}
#endregion
#region 知识点四 泛型方法
//1.普通类中的泛型方法
class GenericTest2
{
//使用的时候传入实际的类型
public void GenericFunction<T>(T value)
{
Console.WriteLine(value);
}
//泛型方法可以重载
public void GenericFunction<T>()
{
//用泛型类型 在里面做一些逻辑处理
//因为没传入之前不知道泛型是什么类型 想设置默认值会报错
//T t = 0;//报错
//T t = null;//报错
//使用 default(类型) 可以得到类型的默认值
T t = default(T);
}
//泛型可以作为返回值
public T GenericFunction<T>(string v)
{
return default(T);
}
//多个泛型占位符的泛型方法
public void GenericFunction<T, K, M>(T t, K k, M m)
{
}
}
//2.泛型类中的泛型方法
//虽然类名也叫GenericTest2 但是和上面的普通类GenericTest2已经不是一个类了
//泛型也可以说是类名的一部分
class GenericTest2<T>
{
public T value;
//这才是泛型方法 实际使用时要传入类型
public void TestFun<K>(K k)
//public void TestFun<T>(T t)//不能叫T了 因为外面的泛型类的泛型占位符也是T 再叫T会分不清楚是谁的
{
Console.WriteLine(k);
}
//这个不叫泛型方法 因为 T是泛型类申明的时候 就指定 在使用这个函数的时候
//我们不能再去动态的变化了
public void TestFun(T t)
{
}
}
#endregion
#region 知识点五 泛型的作用
//1.不同类型对象的相同逻辑处理就可以选择泛型
//2.使用泛型可以一定程度避免装箱拆箱
//举例:优化ArrayList
//传入泛型后 不同类型数组的可以复用代码
class ArrayList<T>
{
private T[] array;
public void Add(T value)
{
}
public void Remove(T value)
{
}
}
#endregion
#region 总结
//1.申明泛型时 它只是一个类型的占位符
//2.泛型真正起作用的时候 是在使用它的时候
//3.泛型占位字母可以有n个用逗号分开
//4.泛型占位字母一般是大写字母
//5.不确定泛型类型时 获取默认值 可以使用default(占位字符)
//6.看到<>包裹的字母 那肯定是泛型
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("泛型");
//主函数内
#region 知识点三 泛型类和泛型接口
//一个泛型占位符的泛型测试类
//泛型占位符T中传入int类型 对应类里的T类型变量value学组就是int类型
SingleGenericClass<int> t = new SingleGenericClass<int>();
t.value = 10;
Console.WriteLine(t.value);//10
//泛型占位符T中传入string类型 对应类里的T类型变量value学组就是string类型
SingleGenericClass<string> t2 = new SingleGenericClass<string>();
t2.value = "123123";
Console.WriteLine(t2.value);//123123
//多个泛型占位符的泛型测试类
//泛型类的占位符也可以填泛型类
MultiGenericClass<int, string, float, double, SingleGenericClass<int>, uint, short> t3 =
new MultiGenericClass<int, string, float, double, SingleGenericClass<int>, uint, short>();
#endregion
#region 知识点四 泛型方法
//普通类中的泛型方法
//new出普通类
GenericTest2 genericTest2 = new GenericTest2();
//调用类的泛型方法时传入类型
genericTest2.GenericFunction<string>("123123");//123123
//泛型类中的泛型方法
//new出泛型类
GenericTest2<int> genericTest_2 = new GenericTest2<int>();
//这个不叫泛型方法 因为 T是泛型类申明的时候 就指定 在使用这个函数的时候
//我们不能再去动态的变化了
genericTest_2.TestFun(10);
//这才是泛型方法 实际使用时要传入类型
genericTest_2.TestFun<string>("123");//123
genericTest_2.TestFun<float>(1.2f);//1.2f
genericTest_2.TestFun(true);
//假如没有同名的方法 甚至可以省略传入类型 会根据传入的参数类型自动传入实际类型
//建议还是要传类型 更清晰
genericTest_2.TestFun<int>(250);//这样用的还是泛型方法
genericTest_2.TestFun(250);
//这样就不是泛型方法了 因为genericTest_2是泛型int类 里面有TestFun(T t)这个方法
//传入int相当于有TestFun(int t)这个方法 会调用到这个方法里 所以想要调用泛型方法不能省略<int>了
#endregion
}
}
}
6.3 练习题
定义一个泛型方法,判断类型并返回类型名称与占有的字节数
class语句块内,主函数外
// 判断类型泛型方法
static string JudgeTypeFunction<T>()
{
if (typeof(T) == typeof(int))
{
return string.Format("{0},{1}字节", "整形", sizeof(int));
}
else if (typeof(T) == typeof(char))
{
return string.Format("{0},{1}字节", "字符", sizeof(char));
}
else if (typeof(T) == typeof(float))
{
return string.Format("{0},{1}字节", "单精度浮点数", sizeof(float));
}
else if (typeof(T) == typeof(string))
{
return string.Format("{0},{1}字节", "字符串", "不定");
}
return "其它类型";
}
主函数内
Console.WriteLine(JudgeTypeFunction<int>()); // 整形,4字节
Console.WriteLine(JudgeTypeFunction<string>()); // 字符串,?字节
Console.WriteLine(JudgeTypeFunction<char>()); // 字符,2字节
Console.WriteLine(JudgeTypeFunction<float>()); // 单精度浮点数,4字节
Console.WriteLine(JudgeTypeFunction<double>()); // 其它类型
Console.WriteLine(JudgeTypeFunction<uint>()); // 其它类型
6.4 练习题代码
using System;
namespace Lesson5_练习题
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("泛型练习题");
//主函数内
#region 练习题一
//定义一个泛型方法,方法内判断该类型为何类型,并返回类型的名称与占有的字节数
//如果是int,则返回“整形,4字节”
//只考虑以下类型
//int:整形
//char:字符
//float:单精度浮点数
//string:字符串
//如果是其它类型,则返回“其它类型”
//(可以通过typeof(类型) == typeof(类型)的方式进行类型判断)
Console.WriteLine(JudgeTypeFunction<int>());//整形,4字节
Console.WriteLine(JudgeTypeFunction<string>());//字符串,?字节
Console.WriteLine(JudgeTypeFunction<char>());//字符,2字节
Console.WriteLine(JudgeTypeFunction<float>());//单精度浮点数,4字节
Console.WriteLine(JudgeTypeFunction<double>());//其它类型
Console.WriteLine(JudgeTypeFunction<uint>());//其它类型
#endregion
}
//class语句块内 主函数外
#region 练习题一
//判断类型泛型方法
static string JudgeTypeFunction<T>()
{
if (typeof(T) == typeof(int))
{
return string.Format("{0},{1}字节", "整形", sizeof(int));
}
else if (typeof(T) == typeof(char))
{
return string.Format("{0},{1}字节", "字符", sizeof(char));
}
else if (typeof(T) == typeof(float))
{
return string.Format("{0},{1}字节", "单精度浮点数", sizeof(float));
}
else if (typeof(T) == typeof(string))
{
return string.Format("{0},{1}字节", "字符串", "?");
}
return "其它类型";
}
#endregion
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com