【发布时间】:2009-11-04 22:50:46
【问题描述】:
我可能走错了方向,所以让我试着整理一下我的想法(希望能从你们那里得到一些提示):
想象一个枚举:
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 用于强制转换。
另外,回到我的构造函数,假设我想向它发送一个图形值,以便我们可以设置 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);
我已经说得够多了。也许这更像是一个设计问题,而不是与枚举相关的问题。我只是在寻找一些关于如何解决这个问题的想法。谢谢!
################################################# ################################ ################################################# ################################ ####################### 编辑从这里开始###################### ################# ################################################# ################################ ################################################# ################################这是对使用泛型的回应(如果我有点慢,我深表歉意;谢谢 Daniel 的回复):
这是一个建议:
ReportInputForm<TrendingReport> = new ReportInputForm<TrendingReport>(GraphType.Area);
好的,所以如果我要使用泛型(和表单),我必须创建一个类型。我在想象这样的事情(我们现在只公开一个函数,设置标题):
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。我正在尝试编译时检查这一点。我肯定也遗漏了一些东西(关于泛型)。
【问题讨论】:
-
对我来说,我觉得这更像是一个设计问题,不是很糟糕,只是需要一些调整以实现可重用性和减少代码混乱。
-
您实际上并不需要“精心设计的继承层次结构”。单个抽象 Report 基类和允许类型的每个子类枚举将为您提供所需的一切,而无需所有复杂的 ifs/switching。