C#enum依赖于另一个枚举[或者这可能与设计相关]

时间:2009-11-04 22:50:47

标签: c# enums

我可能会走错方向,所以让我试着理清我的想法(并希望从你们那里得到一些提示):

想象一下枚举:

public enum ReportType
{
   Performance,
   Trending,
   Statistical
}

此枚举也将是表单构造函数的属性或参数。 ReportType的值将决定如下内容:

a) the text displayed at the top of the form
b) Which controls are visible
c) the text for a combobox <---!!!! this is where the 2nd enum comes in

关于第二个枚举,如果它是一个Performance ReportType,我想要:

public enum PerformanceGraph
{
    Bar,
    Line,
    Pie,
    Area
}

如果是趋势,我希望:

public enum TrendingGraph
{
    Bar,
    Line
}

此表单只是收集用户输入。我的意思是,我宁愿不为一个简单的形式进入一些复杂的继承结构。当我能够快速做出类似的事情时,似乎需要付出很多努力(我可能是错的):

(想象一下这个构造函数)

public ReportInputForm(ReportType RptType)
{
    m_RptType = RptType;

    if (RptType == ReportType.Performance)
    {
        this.Text = "Performance Title";
        this.CheckBoxCtl.Visible = false;
        this.GraphCombo.Items.AddRange(Enum.GetNames(typeof(PerformanceGraph)));
        this.GraphCombo.SelectedIndex = (int)PerformanceGraph.Bar;
    }
    else if (RptType == ReportType.Trending)
    {
         // blah, blah
    }
    else if (RptType == ReportType.Statistical)
    {
        // blah, blah
    }
    else
    {
        throw new ArgumentException("Invalid ReportType enum value");
    }
}

当您想要使用GraphCombo实际执行某些操作时,它开始变得毛茸茸,因为现在您需要知道它是用于投射的ReportType。

另外,回到我的构造函数,假设我想向它发送一个Graph Value,这样我们就可以设置GraphCombo的SelectedIndex(这可能是用户上次选择的值,而不是设置某种类型的默认值)。嗯....

 public ReportInputForm(ReportType RptType, ???WhichGraphEnum???)
 {
 }

我的意思是,现在有三个图形枚举,因为有三个ReportType。另外,想象一下,再添加几个ReportType。

我想我可以使用int / long:

 public ReportInputForm(ReportType RptType, int lastGraphType)
 {
 }

但我想我正在努力成为Enum先生,我的编译时检查。换句话说,如果我可以使用某种类型的枚举(如此),我可以检测到错误:

ReportInputForm foo = new ReportInputForm(ReportType.Trending, GraphType.Area);

相反:

// Is 4 even a valid graph type for the trending report?  Answer: No
ReportInputForm foo = new ReportInputForm(ReportType.Trending, 4);

我已经絮絮叨叨了。也许这更像是一个设计问题而不是枚举相关。我只想找到一些关于如何解决这个问题的想法。谢谢!

################################################## ################################ ################################################## ################################ 编辑开始于此################## ################# ################################################## ################################ ################################################## ################################

这是对使用Generics的回应(如果我有点慢,我道歉;感谢Daniel对你的回复):

这是一个建议:

ReportInputForm<TrendingReport> = new ReportInputForm<TrendingReport>(GraphType.Area);

好的,所以如果我要使用Generics(和Form),我必须创建一个Type。我想象的是这样的事情(我们现在只公开一个函数,设置标题):

public abstract class ReportType
{
    public abstract string GetTitle();
}

public class PerformanceReport : ReportType
{
    public PerformanceReport()
    {
    }

    public override string GetTitle()
    {
        return "This is my Performance title";
    }
}

public class TrendingReport : ReportType
{
    public TrendingReport()
    {
    }

    public override string GetTitle()
    {
        return "This is my Trending title";
    }
}

public partial class Form1<T> : Form
    where T : ReportType, new()
{
    T foo = null;
    public Form1()
    {
        InitializeComponent();
        foo = new T();
        this.Text = foo.GetTitle();
    }
}

所以,现在我可以做一些像建议的那样:

Form1<TrendingReport> f = new Form1<TrendingReport>();

这很酷,而且它有效(我的标题取决于类型),但我不认为这有助于我原来的问题。第二个枚举。

如果我使用的是PerformanceReport,我希望我的GraphType枚举为:

public enum PerformanceGraph
{
    Bar,
    Line,
    Pie,
    Area
}

如果我使用的是TrendingReport,我希望我的GraphType枚举为:

public enum TrendingGraph
{
    Bar,
    Line
}

换句话说,这个枚举取决于班级(或者我原来的问题,取决于第一个词汇)。

我的意思是,我想我可以在抽象类中放入一个包含所有图形类型的枚举:

public abstract class ReportType
{
    public enum GraphType
    {
        Bar,
        Line,
        Pie,
        Area
    }

    public abstract string GetTitle();
}

但是,这违背了我原来问题的目的。因为这现在变得合法(想象我修改了Form1的构造函数):

Form1<TrendingReport> f = new Form1<TrendingReport>(ReportType.GraphType.Pie);

请记住,TrendingReport应该只有Bar和Line。我正在尝试编译时检查这个。我肯定也会遗漏一些东西(关于泛型)。

3 个答案:

答案 0 :(得分:7)

如果表单的类型取决于枚举的值,我会将枚举变为类型本身。然后使表单类通用。

例如:

ReportInputForm<TrendingReport> = new ReportInputForm<TrendingReport>(GraphType.Area);

甚至:

ReportInputForm<AreaGraph> = new TrendingReportForm<AreaGraph>();

假设TrendingReportFormReportInputForm的子类。

如果您的某个行的行为基于某个枚举值而发生更改,您应该寻找机会将更改行为重构为可以委派给子类的单独方法。

答案 1 :(得分:1)

这听起来像是一个非常合理的地方,可以使用继承,基类ReportInputForm和子类PerformanceReportInputFormTrendingReportInputFormStatisticalReportInputForm。它看起来并不特别复杂,它可以在保持编译时类型检查的同时巧妙地避免任何switch / case语句或long。或者,您可以根据策略模式实现它,这会增加一些脚手架和开销,但允许您动态更改报告类型。

答案 2 :(得分:0)

通用表格?

  ReportInputForm<T>