我的上下文是,我正在构建一个简单的工厂方法来创建给定基类型的派生类型的实例。工厂方法只接受一个类型参数,即没有任何参数。这显然可以通过 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/