当类型参数未知但实际上未被使用时,如何针对泛型类型进行模式匹配?
How do I do pattern matching against generic type when type parameter is unknown, but effectively not used?
我有一个 classes 的层次结构来模拟有区别的联合。其中一个 class 是一条记录:
private sealed record ErrorStrWithEnum<TEnum>(string Error, TEnum Enum) : Error
where TEnum : struct, Enum
然后我有一个 Error
类型的对象,我想提取消息:
error switch
{
ErrorStrWithEnum<_>(var message, _) => message
}
这显然行不通。即使 classes 支持协方差,我也无法与 ErrorStrWithEnum<object>(var message, _)
匹配,因为值类型不支持 cov-/contravariance。
替代方法是引入中介类型ErrorStrWithEnum(string Error, object Enum)
但是会造成装箱
还有更优雅的选择吗?
您需要为消息或接口引入带有字符串的非通用记录并与之匹配:
private record ErrorWithStr(string Error) : Error;
private sealed record ErrorStrWithEnum<TEnum>(string Error, TEnum Enum) : ErrorWithStr(Error)
where TEnum : struct, Enum;
error switch
{
ErrorWithStr(var message) => message
}
或
private interface IHaveError {
string Error { get; }
}
private sealed record ErrorStrWithEnum<TEnum>(string Error, TEnum Enum) : Error, IHaveError
where TEnum : struct, Enum
x switch
{
IHaveError err=> err.Error
}
记录可以实现接口,因此您可以将该字符串公开为接口 属性:
private interface IHasMessage {
string Message { get; }
}
private sealed record ErrorStrWithEnum<TEnum>(string Message, TEnum Enum)
: Error, IHasMessage
where TEnum : struct, Enum
{
...
}
那么你可以匹配IHasMessage
:
error switch
{
IHasMessage { Message: var message } => message
}
我有一个 classes 的层次结构来模拟有区别的联合。其中一个 class 是一条记录:
private sealed record ErrorStrWithEnum<TEnum>(string Error, TEnum Enum) : Error
where TEnum : struct, Enum
然后我有一个 Error
类型的对象,我想提取消息:
error switch
{
ErrorStrWithEnum<_>(var message, _) => message
}
这显然行不通。即使 classes 支持协方差,我也无法与 ErrorStrWithEnum<object>(var message, _)
匹配,因为值类型不支持 cov-/contravariance。
替代方法是引入中介类型ErrorStrWithEnum(string Error, object Enum)
但是会造成装箱
还有更优雅的选择吗?
您需要为消息或接口引入带有字符串的非通用记录并与之匹配:
private record ErrorWithStr(string Error) : Error;
private sealed record ErrorStrWithEnum<TEnum>(string Error, TEnum Enum) : ErrorWithStr(Error)
where TEnum : struct, Enum;
error switch
{
ErrorWithStr(var message) => message
}
或
private interface IHaveError {
string Error { get; }
}
private sealed record ErrorStrWithEnum<TEnum>(string Error, TEnum Enum) : Error, IHaveError
where TEnum : struct, Enum
x switch
{
IHaveError err=> err.Error
}
记录可以实现接口,因此您可以将该字符串公开为接口 属性:
private interface IHasMessage {
string Message { get; }
}
private sealed record ErrorStrWithEnum<TEnum>(string Message, TEnum Enum)
: Error, IHasMessage
where TEnum : struct, Enum
{
...
}
那么你可以匹配IHasMessage
:
error switch
{
IHasMessage { Message: var message } => message
}