15.C# —— 多接口,泛型方法,泛型效率、泛型类和泛型接口、泛型约束

目录

一、多接口

[1. 一个类同时实现多个接口](#1. 一个类同时实现多个接口)

[2. 接口继承(接口多继承)](#2. 接口继承(接口多继承))

[3. 抽象类 vs 接口 异同](#3. 抽象类 vs 接口 异同)

相同点

不同点

二、泛型方法

[1. 泛型概念](#1. 泛型概念)

[三、泛型效率(Stopwatch 测速)](#三、泛型效率(Stopwatch 测速))

[四、泛型接口 & 泛型类](#四、泛型接口 & 泛型类)

[1. 泛型接口定义](#1. 泛型接口定义)

[2. 两种实现方式](#2. 两种实现方式)

[五、泛型约束 where](#五、泛型约束 where)

全篇总结


一、多接口

1. 一个类同时实现多个接口

  1. 多个接口成员重名、类型相同:只实现一次即可。
  2. 多个接口成员同名但返回 / 字段类型不同 :必须显式接口实现 ,格式:接口名.成员名,显式实现不能加访问修饰符(默认私有)。

csharp

运行

cs 复制代码
interface IA
{
    int A { get; set; }
    string B { get; set; }
    string C { get; set; }
    void F1();
}
interface IB
{
    string B { get; set; }
    int C { get; set; }
    void F1(int a);
}
class Test : IA, IB
{
    public int A { get; set; }
    public string B { get; set; }
    //显式实现IA的C
    string IA.C { get; set; }
    //显式实现IB的C
    int IB.C { get; set; }
    public void F1() { }
    public void F1(int a) { }
}

使用:想要调用 IA 的 C,变量声明为IA;调用 IB 的 C,变量声明为IB

cs 复制代码
IA t1 = new Test();
t1.C = "11";
IB i1 = new Test();
i1.C = 10;

2. 接口继承(接口多继承)

接口可以继承另一个 / 多个接口;子类实现派生接口时,必须实现所有父接口全部成员

cs 复制代码
interface IC { string B { get; set; } }
interface IQ : IC { int C { get; set; } }
class Test1 : IQ
{
    public int C { get; set; }
    public string B { get; set; }
}

3. 抽象类 vs 接口 异同

相同点
  1. 都不能直接实例化
  2. 都能包含未实现成员,由子类去实现
不同点
  1. 抽象类可包含普通实现方法;接口所有成员默认抽象,不能写方法体
  2. 一个类只能继承一个抽象类 ;可以实现多个接口
  3. 抽象类重写用override;接口实现直接写 public 成员
  4. 抽象类成员可以加访问修饰符;接口成员默认 public,不能手动修饰
  5. 抽象类可以定义字段;接口不能定义实例字段,只能属性、方法

二、泛型方法

1. 泛型概念

泛型:延迟确定数据类型 ,方法定义时不固定参数 / 返回值类型,调用时传入具体类型<T>,一套代码适配多种数据类型。语法:方法名<泛型标识>(参数),常用 T、T1、T2 做泛型符号。

cs 复制代码
//单泛型
static T Test<T>(T a)
{
    return a;
}
//调用,显式指定类型
Test<int>(10);
Test<string>("aa");
//类型推断,省略<>
Test(10);
  • 多泛型参数:<T1,T2>,多个泛型互相独立
cs 复制代码
//两个不同类型参数
static void Test2<T1, T2>(T1 a, T2 b) { }
//参数+泛型数组
static T1 Test3<T1, T2>(T1 a, T2[] b) { return a; }

三、泛型效率(Stopwatch 测速)

三种传参性能对比:

  1. 值类型参数:无装箱拆箱,速度最快
  2. 泛型参数:编译时确定类型,无装箱,速度接近原生值类型
  3. object 参数 :值类型传入发生装箱、取出拆箱,性能最差
cs 复制代码
//Stopwatch用来统计代码执行毫秒
Stopwatch sw = new Stopwatch();
sw.Start();
//循环调用
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

四、泛型接口 & 泛型类

1. 泛型接口定义

接口名称后加<T>,接口内部成员使用 T 代表待定类型

cs 复制代码
interface Ical<T>
{
    T Add(T a, T b);
    T Sub(T a, T b);
}

2. 两种实现方式

  1. 实现时直接固定具体类型:类不再是泛型类

    public class Calc2 : Ical
    {
    public int Add(int a, int b) => a + b;
    public int Sub(int a, int b) => a - b;
    }

  2. 实现时继续沿用泛型 :类也要定义<T>,创建对象时指定类型

    public class Calc1 : Ical
    {
    public T Add(T a, T b) => default(T);
    public T Sub(T a, T b) => default(T);
    }
    //使用
    Calc1 c = new Calc1();

default(T):获取泛型 T 的默认值,值类型默认 0,引用类型默认 null。

五、泛型约束 where

使用where T : 约束缩小泛型可用范围,5 种常用约束:

  1. where T : struct → T只能是值类型(int/double/struct 等)
  2. where T : class → T只能是引用类型(类、接口、string)
  3. where T : new() → T 必须有无参构造函数
  4. where T : 父类名 → T 必须是该类或它的子类
  5. where T : 接口名 → T 必须实现该接口
cs 复制代码
//值类型约束
static void Test2<T>(T a) where T : struct { }
//引用类型约束
static void Test3<T>(T a) where T : class { }
//无参构造约束
static void Test4<T>(T a) where T : new() { }
//父类约束
static void Test5<T>(T a) where T : People { }
//接口约束
static void Test6<T>(T a) where T : IPeople { }

全篇总结

  1. 多接口:同名不同类型成员需要显式接口实现;接口支持多继承。
  2. 泛型方法:<T>定义,调用可类型推断省略尖括号。
  3. 性能:原生值类型 ≈ 泛型 >> object 装箱。
  4. 泛型接口:固定类型实现 / 泛型类延续实现两种写法。
  5. where 约束:struct/class/new ()/ 基类 / 接口五大约束,限制泛型范围。
相关推荐
影寂ldy1 小时前
C# const 常量 / readonly 只读 / static readonly
java·开发语言·c#
iCxhust2 小时前
c#多串口重量采集上位机程序
开发语言·汇编·c#·微机原理·8088单板机
雪豹阿伟2 小时前
14.C# —— 虚方法,new/override,密封类,索引器,接口
c#·上位机
糖果店的幽灵2 小时前
LangChain 1.3 完全教程:从入门到精通-Part 11: Tools(工具系统)
开发语言·langchain·c#
专注VB编程开发20年7 小时前
python翻译网页HTML的难题
python·c#·html
z落落7 小时前
C# 抽象类(abstract)
java·开发语言·c#
unityのkiven9 小时前
工作分享1(26.5.27):基于栈实现全局返回逻辑通用架构设计(适配异步 + 确认弹窗)
游戏·unity·c#·客户端架构
z落落9 小时前
C# 多态 + 函数重载(静态多态)+运算符重载
开发语言·c#
Fms_Sa9 小时前
分治法—最大子段问题
算法·c#