5.4 泛型值(Generic values)

本文探讨了F#中的泛型类型声明,并将其与C#中的泛型进行了比较。介绍了如何利用泛型特性来创建通用的数据结构,如元组和自定义类型构造函数。

5.4 泛型值(Generic values)

 

在本节,我们将讨论泛型类型[原文为generic type,泛型类型,应该可以简称为泛型]声明,可以发现,在很多方面,F# 中的泛型与C# 中的泛型很相似。到目前为止,我们唯一用 type 结构声明的类型,就是差别联合;在后面,我们会看到使用同样结构写的其他类型声明(特别是,在第七和第九章),但是,使类型成为泛型的语法,与现在将要看到的语法完全相同。

不需要事先声明的类型,比如,元组,天生就是泛型。我们可以使用带有任意其他类型的类型的构造函数,比如, int * int 或 string * int;创建元组时,可以使用有任意值的值构造函数,写成 (12,34) 或 ("Pi",3.14)。在本节,我们将学习如何使自己的类型构造函数成为泛型;首先看一下如何在 C# 中实现泛型选项类型。

 

<think>我们被要求解释C#(Generic)的作用,并提供代码示例和解释。然后按照格式提出相关问题。 是C#中一个强大的特性,它允许我们编写可以适用于多种数据类的类、方法、接口等,而无需为每种类单独编写代码。的主要作用是提高代码的重用性、类安全性和性能。 作用: 1. 代码重用:编写一次,适用于多种类。 2.安全:在编译时进行类检查,避免运行时类转换错误。 3. 性能:避免装箱和拆箱操作(对于),提高性能。 常见应用:类、方法、接口、委托。 下面通过几个示例来展示的使用。</think>### C#(Generic)的作用详解 是C#中的核心特性,允许你编写可重用的代码组件,这些组件可以处理不同类的数据,而无需为每种类单独实现。的主要作用是提供**类安全**和**代码重用**,同时避免装箱拆箱带来的性能损耗。 #### 的六大核心作用 1. **类安全性** - 编译时类检查,避免运行时类转换错误 - 消除强制类转换的需要 2. **代码重用** - 单个实现可处理多种数据类 - 减少重复代码 3. **性能优化** - 避免的装箱拆箱操作 - 直接操作原始数据类 4. **集合安全性** - 创建类安全的集合(如`List<T>`) - 防止添加错误类元素 5. **算法通用化** - 编写与数据类无关的通用算法 - 例如排序、搜索等算法 6. **约束灵活性** - 通过约束指定类能力(如`where T : IComparable`) - 平衡灵活性与安全性 --- ### 代码示例 #### 1. 基本类示例 ```csharp using System; // 类定义 public class Box<T> { private T content; public Box(T initialContent) { content = initialContent; } public T GetContent() { return content; } public void UpdateContent(T newContent) { content = newContent; } } class Program { static void Main() { // 整数盒子 Box<int> intBox = new Box<int>(42); Console.WriteLine($"整数内容: {intBox.GetContent()}"); // 字符串盒子 Box<string> strBox = new Box<string>("Hello Generics"); Console.WriteLine($"字符串内容: {strBox.GetContent()}"); // 自定义类盒子 Box<DateTime> dateBox = new Box<DateTime>(DateTime.Now); Console.WriteLine($"日期内容: {dateBox.GetContent()}"); } } ``` **解释**: - `Box<T>`是类,`T`是类参数占位符 - 创建实例时指定具体类(如`Box<int>`) - 同一类可安全处理不同类数据 #### 2. 方法示例 ```csharp using System; class GenericMethods { // 方法:交换两个 public static void Swap<T>(ref T a, ref T b) { T temp = a; a = b; b = temp; } // 方法:查找最大(带约束) public static T Max<T>(T a, T b) where T : IComparable<T> { return a.CompareTo(b) > 0 ? a : b; } } class Program { static void Main() { // 交换整数 int x = 5, y = 10; Console.WriteLine($"交换前: x={x}, y={y}"); GenericMethods.Swap(ref x, ref y); Console.WriteLine($"交换后: x={x}, y={y}"); // 交换字符串 string s1 = "Hello", s2 = "World"; Console.WriteLine($"交换前: s1={s1}, s2={s2}"); GenericMethods.Swap(ref s1, ref s2); Console.WriteLine($"交换后: s1={s1}, s2={s2}"); // 查找最大 double maxDouble = GenericMethods.Max(3.14, 2.71); Console.WriteLine($"较大: {maxDouble}"); string maxString = GenericMethods.Max("Apple", "Banana"); Console.WriteLine($"字母顺序靠后: {maxString}"); } } ``` **解释**: - `Swap<T>`方法可交换任意类变量 - `Max<T>`方法使用约束`where T : IComparable<T>`确保类可比较 - 方法可直接调用,编译器推断类 #### 3. 约束示例 ```csharp using System; public interface IIdentifiable { int Id { get; } } public class Product : IIdentifiable { public int Id { get; set; } public string Name { get; set; } } public class Repository<T> where T : IIdentifiable { private List<T> items = new List<T>(); public void Add(T item) { items.Add(item); } public T GetById(int id) { return items.FirstOrDefault(i => i.Id == id); } } class Program { static void Main() { Repository<Product> productRepo = new Repository<Product>(); productRepo.Add(new Product { Id = 1, Name = "Laptop" }); productRepo.Add(new Product { Id = 2, Name = "Phone" }); Product found = productRepo.GetById(2); Console.WriteLine($"找到产品: {found?.Name}"); // 以下代码会编译错误,因为string不满足IIdentifiable约束 // Repository<string> invalidRepo = new Repository<string>(); } } ``` **解释**: - `where T : IIdentifiable`约束确保`T`实现指定接口 - 在`GetById`方法中可直接访问`Id`属性 - 尝试使用不满足约束的类会导致编译错误 --- ### 与Object的性能对比 ```csharp using System; using System.Collections.Generic; using System.Diagnostics; class PerformanceTest { const int Iterations = 10000000; static void TestGenericList() { List<int> list = new List<int>(); var sw = Stopwatch.StartNew(); for (int i = 0; i < Iterations; i++) { list.Add(i); int value = list[0]; list.RemoveAt(0); } sw.Stop(); Console.WriteLine($"List耗时: {sw.ElapsedMilliseconds}ms"); } static void TestArrayList() { ArrayList list = new ArrayList(); var sw = Stopwatch.StartNew(); for (int i = 0; i < Iterations; i++) { list.Add(i); // 装箱发生 int value = (int)list[0]; // 拆箱发生 list.RemoveAt(0); } sw.Stop(); Console.WriteLine($"ArrayList耗时: {sw.ElapsedMilliseconds}ms"); } static void Main() { TestGenericList(); TestArrayList(); } } ``` **典输出**: ``` List耗时: 520ms ArrayList耗时: 2450ms ``` **性能差异解释**: 1. **装箱拆箱开销**:`ArrayList`存储`object`类需要装箱(内存分配)和拆箱(类转换) 2. **类安全检查**:在编译时完成类检查,`ArrayList`需要运行时检查 3. **内存效率**:直接使用,避免额外内存分配 --- ### 使用最佳实践 1. **优先使用集合**:`List<T>`替代`ArrayList` 2. **合理使用约束**:平衡灵活性与安全性 3. **避免过度化**:只在真正需要通用性的地方使用 4. **考虑协变逆变**:使用`in/out`关键字处理继承关系 5. **命名约定**:单字母类参数(T, K, V)或多字母描述性名称(TKey, TValue) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值