c# - 如何在 C# 中使用 `switch` 仅基于类型参数有条件地分支?

标签 c# .net generics switch-statement type-parameter

我的上下文是,我正在构建一个简单的工厂方法来创建给定基类型的派生类型的实例。工厂方法只接受一个类型参数,即没有任何参数。这显然可以通过 if-else if 结构实现:

public Vehicle Create<T>()
{
    if (typeof(T) == typeof(Car))
        return new Car(); // just an example; could be more complex logic.
    else if (typeof(T) == typeof(Truck))
        return new Truck(); // just an example; could be more complex logic.
    else
        throw new ArgumentException(
            $"The type {typeof(T).Name} is not known by this method.");
}

现在众所周知如何在 C#(从 C# 7.0 开始)中使用模式匹配来根据变量的类型进行分支,但这不适用于类型参数:

switch (T) { ... } // error: "'T' is a type, which is not valid in the given context"

或者...

switch (typeof(T))
{
    case Car c: ... 
    // err: "An expression of type 'Type' cannot be handled by a pattern of type 'Car'"
}

所以我想知道是否可以使用 switch 来达到相同的结果?


研究:我很惊讶以前没有人问过这个问题,但我找不到。我找到了 this post它有一个名称和一些非常接近的答案,但它处理的是(数字)值类型和具有 T 类型参数的方法——泛型类型参数。同样,this post也使用参数。

最佳答案

我知道您的问题专门询问了有关使用 switch 语句的问题,但另一种选择是创建一个以类型为键的工厂字典。

你应该注意到,此时你正在做一个类似于依赖注入(inject)的操作。如果 Create 方法没有创建 X 类型的车辆所需的信息,您正在请求 X 类型的车辆并冒运行时错误的风险。

public class Car : Vehicle { }
public class Truck : Vehicle { }

public abstract class Vehicle
{
    private static readonly IReadOnlyDictionary<Type, Func<Vehicle>> vehicleFactories = new Dictionary<Type, Func<Vehicle>>
    {
        { typeof(Car), () => new Car() },
        { typeof(Truck), () => new Truck() }
    };

    public static Vehicle Create<T>() where T : Vehicle, new()
    {
        if (vehicleFactories.TryGetValue(typeof(T), out var factory))
        {
            return factory();
        }
        else
        {
            throw new ArgumentException(
                $"The type {typeof(T).Name} is not known by this method.");
        }
    }
}

关于c# - 如何在 C# 中使用 `switch` 仅基于类型参数有条件地分支?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55594692/

相关文章:

c# - 从反序列化的 Javascript 重命名属性

c# - 如何让普通的 WebRequest 异步且可等待?

c# - 如何在 LINQ 中根据类型对集合进行排序

.net - 如何在使用 WiX 安装期间加密 app.config 文件部分?

c# - Windows Azure 角色内缓存异常问题

c# - 即使使用具有容量的构造函数,列表 C# 容量始终为 0?

Java泛型——类型推导

C#:整数值在 VS 2008 中以十六进制形式返回

.net - AppDynamics 或 NewRelic 类型的系统 - 它是如何工作的?

generics - 如何重写这个通用参数?