我有一种过滤/搜索方法,现在为每个提供搜索的Windows Form
编写。我正在尝试在基类中创建一个泛型方法,这样我就可以避免这么多的重复代码。
以下是我要修改的原始代码:
private void LoadData()
{
GridFilter filter = new GridFilter();
filter.AddRule(dgvColDescription.DataPropertyName, txtDescription.Text);
if (cboColor.SelectedIndex != -1)
{
filter.AddRule(dgvColMaterialColorId.DataPropertyName, cboColor.SelectedValue.ToString());
}
...
//a lot more of this filter.AddRule stuff
...
}
我认为这里有两件事 - 需要GridFilter
的实例和我需要使用的两种控件。
这里说的是我尝试使用泛型方法:
protected virtual void AddFilterRules<T>(Control ctrl, String str) where T : GridFilter
{
T filter;
if (ctrl is ComboBox)
{
if ((ctrl as ComboBox).SelectedIndex != -1)
{
filter.AddRule(/*dgvColMaterialColorId.DataPropertyName*/ str, (ctrl as ComboBox).SelectedValue.ToString());
}
}
if (ctrl is TextBox)
{
filter.AddRule(/*dgvColCode.DataPropertyName*/str, ctrl.Text);
}
}
有一些评论,因为我仍然不确定我是否可以将评论的部分作为字符串传递,但对我来说更大的问题是我从IDE
关于filter
的错误变量是:
使用未分配的局部变量“filter”
毕竟可以用它来制作通用方法吗?我该怎么做?
答案 0 :(得分:2)
将new()
contraint添加到您的方法中。
protected virtual void AddFilterRules<T>(Control ctrl, String str) where T : GridFilter, new()
然后
T filter = new T();
或者将T in作为参数传递:
protected virtual void AddFilterRules<T>(T filter, Control ctrl, String str) where T : GridFilter
答案 1 :(得分:1)
您的语法是正确的,但您还有其他两个问题:
您没有将T
初始化为任何内容。在您尝试使用它时,它是null
引用。您打算传递T
吗?
你不是用T
做任何事情。你应该返回 T
吗?或者将其分配给其他对象的属性?
如果传入对T
的引用,然后在方法中修改它,则两个问题都解决了:
protected virtual void AddFilterRules<T>(T filter, Control ctrl, String str)
where T : GridFilter
{
...
}
但是在这种情况下,您的方法根本不需要通用:
protected virtual void AddFilterRules(GridFilter filter, Control ctrl, String str)
{
...
}
答案 2 :(得分:1)
为什么要使用通用方法?
如果您的过滤器始终为GridFilter
,则可以在方法中使用该类型。即使您使用像SpecialGridFilter
这样的派生类,这仍然有效。事实上,在您的原始方法中,每次创建一个新的GridFilter
意味着您可以在新方法中执行此操作。因此,尽管您现在已经传递了一些值,但不需要新的方法。
看起来您将类型参数与普通参数混淆。拥有类型参数并不意味着您获得该类型的实例。它只是意味着您可以对不同类型使用相同的算法,而无需为每种类型明确编码。
如果您确实需要通用实现,则可以对泛型参数where T : GridFilter, new()
使用类型约束。这允许您在通用方法中创建new T()
。
新方法将在何处实施?
我不知道现在如何实现GridFilter
,但看起来AddRule
修改了它。如果是这样,您不应每次都创建一个新实例,因为所有更改都将丢失。因此,AddFilterRules
也应该是GridFilter
类的成员,每个表单都应该有一个GridFilter
的实例。
如果您无法更改GridFilter
的实施,您仍然可以使用扩展方法。如果每次在GridFilter
类型上都有扩展方法时创建新的Form
是正确的。这取决于GridFilter
的工作原理。
答案 3 :(得分:0)
您应该创建一个T:
的实例T filter = new GridFilter();
如果T总是为GridFilter
,你也可以用GridFilter替换T:
protected virtual void AddFilterRules<GridFilter>(Control ctrl, String str)
{
GridFilter filter = new GridFilter();
...
}
但是,我认为你根本不应该使用通用方法。您应该创建一个返回GridFilter的方法:
protected virtual GridFilter AddFilterRules(Control ctrl, String str)
{
GridFilter filter = new GridFilter();
...
return filter;
}