如何 return 来自方法的 switch 语句的不确定类型的值

How to return a value of indeterminate type from a switch statement from a method

我有以下 switch 语句:

switch (SomeType)
{
    case SomeType.A:
        var data = (Type_1)SomeType.Data;
    case SomeType.B:
        var data = (Type_2)SomeType.Data;
    case SomeType.C:
        var data = (Type_3) SomeType.Data;
    case SomeType.D:
        var data = (Type_4) SomeType.Data;
    case SomeType.E:
        var data = (Type_5) SomeType.Data;
    case SomeType.F:
        var data = (Type_6) SomeType.Data;
}

我有两个问题:

一个是 switch 语句似乎将整个事情视为一个范围,因此我不能多次设置 var data,我想我可以克服这个问题,因为这需要包装在一个方法中return 是值,所以我可以做类似 return (Type_6) SomeType.Data; 的事情。

第二个问题是如何将其包装在 return 方法中?据我所知,在 C# 中,该方法必须显式定义 return 类型。有什么想法吗?

动态

您可以使用 dynamic 作为 return 类型:

public dynamic GetData()
{
    dynamic data;
    switch (SomeType)
    {
        case SomeType.A:
            data = (Type_1)SomeType.Data;
        case SomeType.B:
            data = (Type_2)SomeType.Data;
        case SomeType.C:
            data = (Type_3) SomeType.Data;
        case SomeType.D:
            data = (Type_4) SomeType.Data;
        case SomeType.E:
            data = (Type_5) SomeType.Data;
        case SomeType.F:
            data = (Type_6) SomeType.Data;
        default: throw new NotSupportedException();
    }
    return data;
}

只需添加一些 break 语句,否则将无法编译。

但动态是 highly contagious - 如果您在一种方法中使用它,它可能会传播到所有使用原始方法的方法。


重构架构

虽然动态是一个快速解决方案,但它并不是最好的解决方案,因为评论员已经指出了这一点。理想情况下,您应该努力尽可能多地保留类型信息 - 它可以简化开发并减少出错的可能性。

您可以为所有可能的数据对象使用一些基础 class 或接口:

    public interface IData
    {
        // Common properties and methods
    }

    public IData GetData()
    {
        return SomeData.Data;
    }

但这可能需要对您的体系结构进行实质性的重新考虑,如果不同的 Data 类型差异太大,这可能会也可能不会。

访客模式

如果是这种情况,那么您可以查看 Visitor Pattern 处理必须以非常不同的方式处理数据的情况。它仍然需要与 return 类型相同的基本接口,但现在它看起来像:

public interface IData
{
    void Accept(IDataVisitor visitor);
}

public interface IDataVisitor
{
    void Visit(DataA data);
    void Visit(DataB data);
    void Visit(DataC data);
}

public class DataA : IData { public void Accept(IDataVisitor visitor) {visitor.Visit(this);}}
public class DataB : IData { public void Accept(IDataVisitor visitor) {visitor.Visit(this);}}
public class DataC :  IData { public void Accept(IDataVisitor visitor) {visitor.Visit(this);}}

public class ConsoleVisitor : IDataVisitor
{
    public void Visit(DataA data)
    {
        Console.WriteLine("A" + data);
    }

    public void Visit(DataB data)
    {
        Console.WriteLine("B" + data);
    }

    public void Visit(DataC data)
    {
        Console.WriteLine("C" + (data);
    }
}