如何通过索引访问和设置C#对象的属性值?
实现HoursOfDay类的索引器访问
需求说明
我有一个模拟一天时段的HoursOfDay类,包含Hour00到Hour23共24个属性,希望不用反射、也不将对象转换为数组/字典,直接像数组或字典那样通过索引访问和设置属性值,支持以下几种访问方式:
var hoursOfDay = new HoursOfDay(); // 三种合法访问方式 var h1 = hoursOfDay[0]; // 数字索引 var h2 = hoursOfDay["0"]; // 单数字字符串 var h3 = hoursOfDay["hour00"]; // 属性名格式字符串
同时支持设置操作:
hoursOfDay[0] = new HourDetailsExample("exampleData"); hoursOfDay["10"] = new HourDetailsExample("morningData"); hoursOfDay["hour23"] = new HourDetailsExample("nightData");
解决方案:实现多类型索引器
在HoursOfDay类中添加int类型索引器和string类型索引器,通过分支判断处理不同的索引输入,直接映射到对应的属性。
完整代码示例
internal class HoursOfDay { [JsonProperty("hour00", NullValueHandling = NullValueHandling.Ignore)] public HourDetailsExample Hour00 { get; set; } [JsonProperty("hour01", NullValueHandling = NullValueHandling.Ignore)] public HourDetailsExample Hour01 { get; set; } // ... 省略Hour02到Hour22的属性定义 ... [JsonProperty("hour23", NullValueHandling = NullValueHandling.Ignore)] public HourDetailsExample Hour23 { get; set; } // int类型索引器:直接接收0-23的小时数 public HourDetailsExample this[int hour] { get { return hour switch { 0 => Hour00, 1 => Hour01, 2 => Hour02, // ... 依次补充3到22的映射 ... 23 => Hour23, _ => throw new ArgumentOutOfRangeException(nameof(hour), "小时数必须在0-23之间") }; } set { switch (hour) { case 0: Hour00 = value; break; case 1: Hour01 = value; break; case 2: Hour02 = value; break; // ... 依次补充3到22的映射 ... case 23: Hour23 = value; break; default: throw new ArgumentOutOfRangeException(nameof(hour), "小时数必须在0-23之间"); } } } // string类型索引器:支持"0"/"00"/"hour00"三种格式 public HourDetailsExample this[string index] { get { // 处理带前缀的情况,比如"hour00" if (index.StartsWith("hour", StringComparison.OrdinalIgnoreCase)) { var hourStr = index.Substring(4); if (int.TryParse(hourStr, out int hour)) { return this[hour]; } } // 处理纯数字字符串,比如"0"或"00" else if (int.TryParse(index, out int hour)) { return this[hour]; } throw new ArgumentException("索引格式不合法,支持格式:0-23数字、\"0\"/\"00\"字符串、\"hour00\"格式字符串", nameof(index)); } set { // 复用get的逻辑转换为int索引,再调用int索引器的set if (index.StartsWith("hour", StringComparison.OrdinalIgnoreCase)) { var hourStr = index.Substring(4); if (int.TryParse(hourStr, out int hour)) { this[hour] = value; return; } } else if (int.TryParse(index, out int hour)) { this[hour] = value; return; } throw new ArgumentException("索引格式不合法,支持格式:0-23数字、\"0\"/\"00\"字符串、\"hour00\"格式字符串", nameof(index)); } } } // 假设HourDetailsExample类定义如下 public class HourDetailsExample { public string Data { get; set; } public HourDetailsExample(string data) { Data = data; } }
代码说明
- int类型索引器:直接接收0-23的整数,通过switch表达式(get)和switch语句(set)映射到对应的
HourXX属性,超出范围抛出异常。 - string类型索引器:
- 自动识别三种输入格式:带"hour"前缀的字符串、纯数字字符串(单/两位)
- 将合法的字符串索引转换为int索引,复用int索引器的逻辑,减少代码重复
- 非法格式直接抛出明确的参数异常
- 全程未使用反射,也没有将属性转换为数组/字典,完全直接操作类的属性,性能和类型安全性都有保障。
内容的提问来源于stack exchange,提问作者jtmaps
相关产品推荐
相关产品推荐

