索引器、泛型约束

一、索引器

1.索引器是什么?

索引器是一种特殊的
成员类,它能够让对象以类似数组的方式来存取,使程序看起来更为直观,更容易编写

2.如何给类添加索引器?

添加一个this[int index]属性,这个属性类型是 集合里面存储的类型

public People this[int index]

3.如何给索引器添加重载?
public People this[string index]
{
    get
    {
        //获取Lists其中一个元素 根据对象的名字取出元素,根据name='张三’,找张三整体对象
        for (int i = 0; i < Lists.Count; i++)
        {
            if (Lists[i].Name==index)
            {
                return Lists[i];
            }
        }
        return null;
    }
    set
    {
        for (int i = 0; i < Lists.Count; i++)
        {
            if (Lists[i].Name == index)
            {
                Lists[i] = value;
                break;
            }
        }
    }
}

二、泛型约束

1.泛型是什么?

所谓泛型,即通过参数化类型来实现在同一份代码上操作多种数据类型,泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用

在定义泛型类时,可以对代码能够在实例化类时用于类型参数的类型种类施加限制。如果代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。这些限制称为约束。约束是使用 where 上下文关键字指定的

2.五种类型的约束有那些?

1 值类型泛型约束:只允许泛型为值类型 T 只能是值类型

public void F1<T>(T a) where T : struct
{

}

2 引用类型泛型约束:只允许泛型为引用类型 T 只能是引用类型

public void F2<T>(T a) where T : class
{

}

3 某个类的泛型约束::只允许泛型为该类或者子类 T 只能是Stu类型 或者Stu的子类

public void F3<T>(T a) where T : Stu
{

}

4 接口的泛型约束:只允许泛型为实现这个接口的类或者子类 T 只能是Boy类型 或者Boy的子类

public void F4<T>(T a) where T : IMan
{

}

 5 U泛型约束, T的只能是U提供的类型,或者U的子类,T要么是U类型,要么是U子类

public void F5<T,U>(T a,U b) where T : U
{

}

### 关于 Go 中的全面解析 #### 声明与类约束 在 Go 语言中,引入是为了增强代码的灵活性和重用性。通过使用,开发者能够编写适用于多种类的函数或数据结构而无需重复编码。 对于的声明,在定义时可以通过指定类参数来创建通用版本的方法或结构体[^1]: ```go func Example[T any](value T) { fmt.Println(value) } ``` 这里 `T` 就是类参数,表示该函数可以接受任意类的输入并打印出来。然而,“任意类”的范围有时过宽,因此需要更精确地控制哪些类能被允许传递给函数或结构体成员变量——这就是所谓的 **类约束**。 类约束使得我们可以限定传入的具体类必须满足某些条件,比如实现了特定接口或是属于某个具体的基础类集合。这通常借助于预定义好的接口或者自定义接口完成[^3]: ```go type Number interface { ~int | ~float64 } func SumNumbers[N Number](a, b N) N { return a + b } ``` 上述例子展示了如何利用联合类(union types)来构建一个名为 `Number` 的接口,它只接受整数 (`~int`) 或浮点数 (`~float64`) 类作为其实现者;接着定义了一个加法运算函数 `SumNumbers` ,其操作数仅限于这些数值类。 #### 函数的应用实例 当涉及到实际应用时,考虑如下场景:有一个需求是要处理不同长度固定大小的整形数组,并对其进行求和计算。由于每种尺寸都对应着不同的静态类 `[i32; n]`,如果不采用,则需分别为各个情况写单独的逻辑实现。有了支持之后就可以简化成这样: ```go // 定义一个用于描述可变长切片的行为特征的接口 type SliceOps interface { Len() int // 获取元素数量 Index(int) int // 访问索引处的值 } // 实现针对定长数组的操作集 func (arr *[N]int) Len() int { return len(*arr) } func (arr *[N]int) Index(i int) int { return (*arr)[i] } // 创建一个通用的求数组总和的函数 func ArraySum[S SliceOps, const N int](slice S) int { sum := 0 for i := 0; i < slice.Len(); i++ { sum += slice.Index(i) } return sum } // 测试案例 fmt.Printf("The sum of array is %d\n", ArraySum([...]int{1, 2, 3})) ``` 这段代码片段说明了怎样运用机制去设计既安全又高效的算法,同时保持良好的抽象层次。 #### 结合特性的结构体示例 除了简单的函数外,还可以将特性融入到复杂的数据模之中。例如之前提到过的程序员信息记录结构体 `Programmer` 可以进一步扩展为带有字段的形式[^2]: ```go type Programmer[L comparable] struct { Name string Age int Job string Language L } var p = Programmer[string]{Name: "Alice", Age: 30, Job: "Developer", Language: "Go"} ``` 在这个改进后的版本里,`Language` 字段不再局限于字符串列表形式,而是变成了一个受制于 `comparable` 接口的参数 `L` 。这意味着它可以容纳任何具备比较能力的对象,从而增加了程序表达上的自由度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值