C#能否实现类似TypeScript中string|string[]的联合自定义类型?
当然可以!C#里虽然没有TypeScript那种直接写string | string[]的联合类型语法,但有好几种方式能实现类似的效果,我给你分享几个常用的方案:
方案1:用结构体+隐式转换模拟
这种方式可以让你像使用原生类型一样直接给自定义类型赋值string或者string[],非常接近TypeScript的使用体验:
public struct MyStringType { private readonly object _value; // 私有构造函数,确保只能通过隐式转换创建实例 private MyStringType(object value) { _value = value ?? throw new ArgumentNullException(nameof(value)); } // 隐式转换:允许直接把string赋值给MyStringType public static implicit operator MyStringType(string value) { return new MyStringType(value); } // 隐式转换:允许直接把string[]赋值给MyStringType public static implicit operator MyStringType(string[] value) { return new MyStringType(value); } // 安全获取string类型的值 public bool TryGetString(out string result) { result = _value as string; return result != null; } // 安全获取string[]类型的值 public bool TryGetStringArray(out string[] result) { result = _value as string[]; return result != null; } // 通用取值方法(需要指定类型) public T? GetValue<T>() where T : class { return _value as T; } }
使用示例
// 直接赋值,和TypeScript一样方便 MyStringType singleString = "Hello World"; MyStringType stringArray = new[] { "Apple", "Banana", "Cherry" }; // 使用时通过类型检查获取实际值 if (singleString.TryGetString(out var str)) { Console.WriteLine($"Single string content: {str}"); } if (stringArray.TryGetStringArray(out var arr)) { Console.WriteLine($"Array has {arr.Length} elements"); }
方案2:用抽象类实现受约束的“判别联合”
如果想要更严格的类型安全(避免不小心存入其他类型的值),可以用抽象类+密封子类的方式实现判别联合,这也是C#里模拟联合类型的推荐方式:
public abstract class MyStringType { // 私有构造函数,确保只有内部子类能继承 private MyStringType() { } // 表示单个字符串的子类 public sealed class SingleString : MyStringType { public string Value { get; } public SingleString(string value) { Value = value ?? throw new ArgumentNullException(nameof(value)); } } // 表示字符串数组的子类 public sealed class StringArray : MyStringType { public string[] Value { get; } public StringArray(string[] value) { Value = value ?? throw new ArgumentNullException(nameof(value)); } } // 提供便捷的创建方法 public static MyStringType FromString(string value) => new SingleString(value); public static MyStringType FromStringArray(string[] value) => new StringArray(value); }
使用示例
MyStringType myValue = MyStringType.FromString("Test"); MyStringType myArray = MyStringType.FromStringArray(new[] { "X", "Y", "Z" }); // 使用模式匹配处理不同类型,编译时就能确保覆盖所有情况 switch (myValue) { case MyStringType.SingleString single: Console.WriteLine($"Got single string: {single.Value}"); break; case MyStringType.StringArray array: Console.WriteLine($"Got array with {array.Value.Length} items"); break; }
方案3:使用第三方库简化实现
如果不想自己写这些模板代码,可以用成熟的第三方库,比如OneOf(可以通过NuGet安装),它专门用来处理C#里的联合类型,语法非常接近TypeScript:
using OneOf; // 直接定义联合类型,和TypeScript的写法几乎一致 using MyStringType = OneOf<string, string[]>; // 使用示例 MyStringType value = "Hello"; value = new[] { "A", "B", "C" }; // 用Switch方法快速处理不同类型 value.Switch( str => Console.WriteLine($"String content: {str}"), arr => Console.WriteLine($"Array length: {arr.Length}") );
总结
- 如果追求最接近TypeScript的使用体验,选方案1;
- 如果需要严格的类型安全,避免非法值,选方案2;
- 如果想少写模板代码,选方案3的第三方库。
内容的提问来源于stack exchange,提问作者ShanieMoonlight
相关产品推荐
相关产品推荐

