【问题标题】:How to switch on types with/when using nullable types?如何使用/何时使用可空类型打开类型?
【发布时间】:2021-10-24 21:03:36
【问题描述】:

我以前知道this question has been asked multiple times,但是I've checked all I could not find any solution 那里没有一个专门处理/讨论可空类型。

用例

我想动态生成测试数据。为此,我传入的value 可以有不同的类型,我需要将它(通过CreateSomething)转换为某些数据类型,例如一个特殊格式的字符串。为此,我有如下所示的辅助函数。 一个示例是生成一个示例 XML 文件,以供以后在生产中针对系统进行测试时使用。然后使用value 断言正确的预期输出。

请注意,对于某些类型,我需要特殊处理,例如将布尔值转换为整数(如下所示),这就是我需要开关的原因。此外,生成的字符串提到了测试数据的类型(尽管它与 C# 中的所有类型不匹配/使用其他名称,例如布尔值被定义为整数)。

可能的例子

在 C# 8.0 中,这是可能的:

public static string GetSomething(object? value) =>
    value switch
    {
        bool boolValue => CreateSomething("Integer", boolValue
            ? 1
            : 0),
        string stringValue => CreateSomething("String", stringValue),
        int numericValue => CreateSomething("String", numericValue.ToString()),
        null => CreateSomething("String", value),
        _ => throw new ArgumentOutOfRangeException(nameof(value))
    };

CreateSomething 是这样定义的:

string CreateSomething(string customType, object? value)

问题

但是,对于null 案例(如上所示),我还想处理类型。 正如您在其他情况下看到的那样,我想将所有bool 值作为第一个参数传递给Integer,并将String 传递给所有其他参数。 当然,value 是并保持null,但这是意料之中的,我只想保留信息/传递有关它应该期望什么类型的信息/在我的测试数据中定义事物,因为否则它被定义为另一种数据类型,因此不会产生尽可能真实的测试数据(不考虑类型)。

尝试

我想在那里使用第二个 switch 语句/或使用.GetType,但当然,在null 上的.GetType 不会像.GetType 那样工作,会抛出NullReferenceException。 我还研究了通过Nullable.GetUnderlyingType(value) 获取可为空的底层类型,但这也不起作用。而this question to get the type from null 只有使用泛型的答案,在我的情况下我不想要。 毕竟,我确实有这个不错的 C# switch type pattern matching 语句可以用于所有类型 - 为什么我不能也将它用于可空类型?

想法解决方案

毕竟,这将是理想的:

/* Code does not work! Only demonstration! */
public static string GetSomething(object? value) =>
    value switch
    {
        bool? boolValue => CreateSomething("Integer", boolValue == null
            ? null : (boolValue ? 1 : 0),
        string? stringValue => CreateSomething("String", stringValue),
        int? numericValue => CreateSomething("String", numericValue?.ToString()),
        _ => throw new ArgumentOutOfRangeException(nameof(value))
    };

当然,我试过了,还是不行。

它只是向我显示错误 CS8400(“功能类型模式在 C# 8.0 中不可用。请使用语言版本 9.0 或更高版本。”)和“类型测试模式需要指定变量或在之后丢弃。”。 即使我使用 C# 9,它也会破坏语法,而不再向我显示任何显式编译器错误。

【问题讨论】:

  • 您要完成的工作不是很清楚。您能否举一些调用您的方法的示例以及您希望它们做什么?
  • 我认为您必须包含您期望的类型,不是吗?如果您的上一个示例有效,则无论何时您传递nullbool? 模式都会匹配,因为null 不包含存储信息。无法判断 nullint? 还是 bool?Foo?,因为它不是对任何东西的引用。
  • @DM 是的,谢谢,显然没有办法让它像我想要的那样运行。看来我需要使用泛型或Type 参数来传递类型。

标签: c# .net-core switch-statement nullable c#-8.0


【解决方案1】:

问题是您试图打开可空类型。那是行不通的。假设有人这样调用你的函数:

GetSomething(null);

GetSomething 函数应该将其视为什么?可以为空的布尔值?一个可以为空的int?没办法说。

您需要先检查 null ,然后将其他可能性视为正常类型。也许是这样?

public static string GetSomething(object? value)
{
    if (value == null)
        return "null";

    return value switch
    {
        bool boolValue     => CreateSomething("Integer", boolValue ? 1 : 0),
        string stringValue => CreateSomething("String",  stringValue),
        int numericValue   => CreateSomething("String",  numericValue.ToString()),
        null               => CreateSomething("String",  value),
        _                  => throw new ArgumentOutOfRangeException(nameof(value))
    };
}

如果您确实需要为 null 的 bool 和 null 的 int 提供不同的东西,那么您还需要传入您希望读取的数据类型。像这样

public static string GetSomething(object? value, Type expectedType)

【讨论】:

  • 它与你的不同之处在于它打开了boolintstring,而不是bool?int?string? 诚然我猜你的意图是以某种方式显示与为空的bool? 与为空的int? 不同的行为。如果您可以为任何为 null 的值返回相同的值,那么我的第一种方法(减去冗余的 null 检查)就可以了。如果您需要与预期 bool 的空值和预期 int 的空值不同的行为,那么您必须传入类型信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-30
  • 2018-03-27
  • 2017-09-25
  • 1970-01-01
  • 2017-01-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多