简体   繁体   中英

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

I have the following switch statement:

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;
}

I have two problems with this:

One being the switch statement seems to treat the whole thing as one scope, therefore I can't set var data multiple times, I think I can overcome this because this needs to be wrapped in a method that returns the value, so I can just do something like return (Type_6) SomeType.Data; .

The second problem is how can I wrap this in a return method? As far as I know in C# the method must explicitly define the return type. Any ideas?

Dynamic

You can use dynamic as a return type:

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;
}

Just add some break statements or it won't compile.

But dynamic is highly contagious - if you use it in one method it will probably propagate through all methods that use the original method.


Reworking architecture

While dynamic is a quick fix, it is not the best solution, as it has been already pointed by commentators. Ideally, you should strive to preserve type information as much as possible - it simplifies development and reduces the likelihood of mistakes.

You can use some base class or interface for all your possible data objects:

    public interface IData
    {
        // Common properties and methods
    }

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

But it may require a substantial reconsideration of your architecture, that may or may not be possible if different Data types differ too much.

Visitor Pattern

If it is the case, then you may take a look at Visitor Pattern that deals with cases when you data has to be processed very differently. It still requires the same base interface as return type, but now it will look like:

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);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM