制作通用方法

时间:2013-03-01 14:43:44

标签: c# generics

我有一种过滤/搜索方法,现在为每个提供搜索的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”

毕竟可以用它来制作通用方法吗?我该怎么做?

4 个答案:

答案 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)

您的语法是正确的,但您还有其他两个问题:

  1. 您没有将T初始化为任何内容。在您尝试使用它时,它是null引用。您打算传递T吗?

  2. 你不是T做任何事情。你应该返回 T吗?或者将其分配给其他对象的属性?

  3. 如果传入对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;
}