如何在C#中创建可表示Dictionary或其列表的自定义类型
在C#中实现支持字典或字典列表的自定义类型
C#作为静态类型语言,没有Python/TypeScript那样直接的联合类型(Union)语法,但可以通过以下几种方式实现类似效果:
1. 基于object的类型检查(简单但不够安全)
直接用object作为类型载体,赋值时可以是字典或字典列表,使用时通过模式匹配区分类型:
// 声明变量 object customValue; // 赋值示例 customValue = new Dictionary<string, object> { { "key", "value" } }; customValue = new List<Dictionary<string, object>> { new Dictionary<string, object> { { "key1", "value1" } }, new Dictionary<string, object> { { "key2", "value2" } } }; // 使用时的类型判断 if (customValue is Dictionary<string, object> singleDict) { // 处理单个字典逻辑 Console.WriteLine(singleDict["key"]); } else if (customValue is List<Dictionary<string, object>> dictList) { // 处理字典列表逻辑 foreach (var dict in dictList) { Console.WriteLine(dict.Keys.First()); } }
这种方式最接近你Python/TypeScript的写法,但缺点是编译时无法保证类型正确性,需要运行时检查。
2. 自定义封装类(类型安全,推荐)
创建一个专门的类来封装两种情况,通过工厂方法确保只有一种类型被赋值:
public class CustomType { // 两个互斥的属性,只有一个会有值 public Dictionary<string, object>? SingleDictionary { get; } public List<Dictionary<string, object>>? DictionaryList { get; } // 私有构造函数,禁止直接实例化 private CustomType(Dictionary<string, object>? singleDict, List<Dictionary<string, object>>? dictList) { SingleDictionary = singleDict; DictionaryList = dictList; } // 工厂方法:创建单个字典实例 public static CustomType FromSingleDict(Dictionary<string, object> dict) { return new CustomType(dict, null); } // 工厂方法:创建字典列表实例 public static CustomType FromDictList(List<Dictionary<string, object>> list) { return new CustomType(null, list); } // 辅助方法:判断当前是哪种类型 public bool IsSingleDict() => SingleDictionary != null; public bool IsDictList() => DictionaryList != null; }
使用示例:
var singleDictType = CustomType.FromSingleDict(new Dictionary<string, object> { { "key", "value" } }); var listType = CustomType.FromDictList(new List<Dictionary<string, object>>()); if (singleDictType.IsSingleDict()) { // 处理单个字典 }
这种方式完全类型安全,编译时就能避免错误赋值,适合大型项目使用。
3. 模拟可辨识联合(C# 9.0+)
利用C#的模式匹配和隐式转换,实现类似联合类型的效果:
public readonly struct CustomType { private readonly object _innerValue; private CustomType(object value) => _innerValue = value; // 隐式转换:字典转CustomType public static implicit operator CustomType(Dictionary<string, object> dict) => new CustomType(dict); // 隐式转换:字典列表转CustomType public static implicit operator CustomType(List<Dictionary<string, object>> list) => new CustomType(list); // 匹配方法:统一处理两种类型的逻辑 public TResult Match<TResult>( Func<Dictionary<string, object>, TResult> handleSingleDict, Func<List<Dictionary<string, object>>, TResult> handleDictList) { return _innerValue switch { Dictionary<string, object> dict => handleSingleDict(dict), List<Dictionary<string, object>> list => handleDictList(list), _ => throw new InvalidOperationException("无效的CustomType类型") }; } }
使用示例:
CustomType customVal = new Dictionary<string, object> { { "key", "test" } }; // 或者直接赋值列表 // CustomType customVal = new List<Dictionary<string, object>>(); var result = customVal.Match( singleDict => $"单个字典:{singleDict["key"]}", dictList => $"字典列表,共{dictList.Count}个元素" ); Console.WriteLine(result);
这种方式兼顾了类型安全和使用便捷性,是比较现代化的实现方式。
4. 使用dynamic(不推荐)
如果不需要编译时类型检查,可以用dynamic直接赋值,但会丢失类型安全,运行时可能出错:
dynamic customVal = new Dictionary<string, object>(); customVal = new List<Dictionary<string, object>>(); // 使用时直接调用成员,但类型错误会抛出运行时异常 Console.WriteLine(customVal.Count);
内容的提问来源于stack exchange,提问作者Sam Germain
相关产品推荐
相关产品推荐

