【问题标题】:Use switch with type Class in generic method在泛型方法中使用类型为 Class 的 switch
【发布时间】:2019-02-06 12:40:42
【问题描述】:

在泛型方法中比较类时是否可以使用开关? 示例:

switch (typeof(T))
{
    case typeof(Class1):
        // ...
        break;

    case typeof(Class2):
        // ...
        break;

    default:
        break;
}

这个想法不是使用名称而是使用 Class 对象。 目前我正在使用:

if (typeof(T) == typeof(Class1))
{
   // ...
}
else if (typeof(T) == typeof(Class2))
{
   // ...
}

为简单起见,最好使用开关。

【问题讨论】:

  • C# v7.1 模式开关对您没有帮助:An expression of type 'T' cannot be handled by a pattern of type 'Class1'。我认为您的if / else if 模式与您将获得的一样好
  • create a string which depends on the Class properties, which again can vary from Class1 to Class2. 这些字符串是什么样的?您应该考虑将该逻辑添加到类(Class1 等)本身中,而不是添加到此方法中。然后这个方法可以调用你添加到Class1/Class2等的方法(如果你有一个定义方法的接口更好,每个类都实现)。
  • @ptuga 您是否将 C# 版本与 .NET 版本混为一谈?
  • 原始副本在 .NET 4.5 @ptuga - stackoverflow.com/a/42488315/34092 上运行良好 - 模式匹配只是语法糖。您使用的是什么 IDE?
  • @ptuga 假设 Visual Studio 2017+,那么使用 C# 7 应该没问题。语言版本不会影响您的框架目标。

标签: c# .net-4.5 c#-5.0


【解决方案1】:

在这种情况下,我使用字典,并与适合手头特定问题的 lambda 值配对。

var options = new Dictionary<Type, Action>()
{
    { typeof(string), () => doSomething() },
    { typeof(int), () => doSomething() },
    ...
};

Action act = null;
if (options.TryGetValue(typeof(T), out act) {
    act();
} else {
   // default
}

字典通常是static readonly 字段或属性,因此索引只完成一次。

在您的具体情况下,您可以使用Dictionary&lt;Type, Func&lt;object, string&gt;&gt;,如下所示:

private static readonly Formatters = new Dictionary<Type, Func<object, string>>()
{
    { typeof(Class1), o => ((Class1)o).format() },
    { typeof(Class2), o => FormatClass.FormatClass2((Class2)o) },
    ...
};

T instance;
string formatted = Formatters[typeof(T)](instance);

【讨论】:

  • 这个选项并不比If/else ifsolution 简单。
  • 这取决于你认为是简单的。我发现它更紧凑(通常是 1 行/类而不是 4 行)并且很容易检查。 10 个类很容易在字典中查到,而不是在代码中查到那么容易。最后但并非最不重要的一点是,拥有一本字典可以让您使整个事情变得可配置。坦率地说,我更关心易于维护和可读性,而不是简单性。 YMMV,
  • @ptuga 是的。我提供的解决方案允许您这样做。您需要将对象转换为特定类型。但无论如何你都需要它。转换为特定类型后,您可以访问该特定类的属性。如果您不想强制转换,则不需要开关:您需要通用抽象类的类型化实现。
  • 这个想法是像在开关中一样执行我的代码。 doSomething() 意味着我的方法之外的东西,并且不区分不同的 T。因为我需要使用类的道具,例如对于 Class1 可能是字符串 s = prop1 + "\t" + prop2 在 Class2 上可能是不同的字符串 s = prop2 + "\t" + prop3(它甚至可以是 List)。不确定这是否可以帮助我。我没有足够的知识来理解它。
  • @ptuga 那么我建议您尝试一下,直到您理解为止。如果有不明白的地方,请告诉我。
【解决方案2】:

扩展 Anu Viswananswer,从 C# 7.1 开始,这是有效的:

public void Method<T>(T param)
{
    switch (param)
    {
        case A a:
            Console.WriteLine("A");
            break;
        case B b:
            Console.WriteLine("B");
            break;
    }
}

【讨论】:

    【解决方案3】:

    如果您使用的是 C# 7,则可以使用模式匹配。

    例如,

    public void Method<T>(T param)
    {
        switch(param)
        {
            case var _ when param is A:
            Console.WriteLine("A");
            break;
            case var _ when param is B:
            Console.WriteLine("B");
            break;
    
        }
    }
    

    在哪里

    public class A{}
    public class B{}
    

    【讨论】:

      猜你喜欢
      • 2018-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-11
      • 1970-01-01
      • 1970-01-01
      • 2022-08-17
      • 1970-01-01
      相关资源
      最近更新 更多