【问题标题】:Is there an efficient way of calling the same method on all objects of type T?有没有一种对 T 类型的所有对象调用相同方法的有效方法?
【发布时间】:2014-10-13 10:20:08
【问题描述】:

假设我有 10 个文本框,它们都有不同的值,但它们都是文本框。而且,我有一个方法CheckInputValue(Textbox tb)。现在,单击一个按钮,我想要检查所有文本框并确定该值是否允许的方法。

但我不想这样做:

        void DoWork()
    {
        CheckInputValue(t1);
        CheckInputValue(t2);
        CheckInputValue(t3);
        CheckInputValue(t4);
        ...
        CheckInputValue(tx);

    }

请注意:以上仅为示例。

我有一个复杂的方法,需要在多个相同类型的控件上执行,我有大约 25 个控件。有没有更优雅的方式来做到这一点? 谢谢。

【问题讨论】:

  • 我认为您不应该验证控件内的数据。您应该验证视图模型中的数据。在这种情况下,您可以向视图模型的属性添加一个属性(即 [Validate]),当您需要时,您可以收集所有具有该属性的属性并验证值。
  • 很难创建一组您想要评估的所有控件吗?这似乎是最困难的部分。
  • 某些集合中的控件是否实现了IEnumerable<T>
  • 这是一个有趣的问题。我(但我也是初学者)会认为您必须在某个时候或其他时候进行写作,这取决于您要重复的部分。你可以例如将您要使用的所有文本框CheckInputValue 添加到List(或一些IEnumerable<TextBox>),然后使用foreach。这将具有(小)优势,您不必添加 every TextBox,而您似乎搜索的方法将在 all TextBoxes 上执行,并且可能有一些你不想被使用。
  • @IvanZub 这只是一个例子。我需要在几个控件上调用一个方法,我觉得像 Method(i1)、Method(i2)、Method(in) 这样调用方法 n 次不是很优雅。

标签: c# windows-phone-8 methods repeat


【解决方案1】:

如果列表中有所有t,则可以使用List<T>.ForEach

listWithT.ForEach(CheckInputValue);

或者用普通的foreach循环遍历它们:

foreach (T t in list)
{
    CheckInputValue(t);
}

或者创建一个内联数组:

foreach (T t in new T[] { t1, t2, t3 })
{
    CheckInputValue(t);
}

如果没有,就没有简单的方法。

【讨论】:

  • 坦率地说,如果你把它们放在一个列表中,你可以foreach - 它会更简单、更高效;p 但它会起作用
  • @MarcGravell:已编辑。
  • 我喜欢使用 foreach 创建内联数组的想法 :) 但是由于我有很多控制权,我是否必须手动指定控件的名称?我问这个是因为 - 我所有的控件都被恰当地命名为 i1、i2、i3...ix
  • @NavikGoswami:有,就像 Benji 回答的那样,但是这样的代码是在问问题。我强烈建议不要使用它!
  • @Navik“适当地”不完全......嗯,适当......你的控件应该有更多的描述性名称,除非它们是实际列表的一部分,在这种情况下你应该管理它们通过根据需要从表单中添加/删除它们来动态地添加/删除它们。 (在这种情况下,您已经将它们列在列表中)。
【解决方案2】:

对不起,如果我的要求有点太高了,但还有更多 将控件添加到列表中的优雅方式,例如 i++ 因为我所有的控件都被命名为 i1, i2, i3....ix :S

你可以这样做(但它很脏):

int n_tbx = 5;
List<TextBox> tbxList = new List<TextBox>();

for (int i = 0; i < n_tbx; i++)
{
    //Where "this" is your mainframe
    tbxList.Add(this.Controls.Find("t"+i, true).FirstOrDefault() as TextBox);
}

foreach (Textbox tbx in tbxList)
{
    CheckInputValue(tbx);
}

【讨论】:

  • 是的,你是对的。我想我最好手动将它们添加到列表中。而且我认为您不能在 Windows Phone 应用程序中使用 this.Controls
【解决方案3】:

我想我知道如何让它变得更简单一些,并且以更多的 MVVM 方式。它被简化了 - 没有属性更改报告,没有输入属性和东西..只是为了让你明白。 因此,主要思想是您可以使用某种属性(在这种情况下为 ValidateAttribute)标记应验证的所有属性,并使用单个 Validate 方法可以收集所有属性并在一个地方对其进行验证。

class SampleViewModel
{
    [Validate]
    public string SomeProperty { get; set; }

    [Validate]
    public string AnotherProperty { get; set; }

    public void Validate()
    {
        foreach (var propertyInfo in GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.IsDefined(typeof(ValidateAttribute), true)))
        {
            var value = propertyInfo.GetValue(this, null);
            Validate(value as string);
        }
    }

    private void Validate(string value)
    {
        if (string.IsNullOrEmpty(value))
        {
            // do something with the invalid input, i.e. throw the exception
        }
    }
}

class ValidateAttribute : Attribute
{
}

【讨论】:

    【解决方案4】:

    你可以这样做:

    List<TextBox> tbxList = new List<TextBox>()
    {
        t1,
        t2,
        t3,
        t4
    };
    
    foreach (Textbox tbx in tbxList)
    {
        CheckInputValue(tbx);
    }
    

    【讨论】:

    • 对不起,如果我有点太苛刻了,但有没有更优雅的方式将控件添加到列表中,比如 i++,因为我所有的控件都被命名为 i1、i2、i3.. ..ix :S
    • 或者我必须像 i1, i2....ix 那样手动编写它们吗? P.S 有很多这样的控件!
    • 我知道我每次都必须将数字增加到控件的基本名称,但我不知道如何在 List&lt;TextBox&gt; tbxList = new List&lt;TextBox&gt;() {}; 之间添加它对不起: S
    • 但是我对您的回答很满意,并将这样标记它。非常感谢您的帮助!
    【解决方案5】:

    我想在上一个答案的基础上,让代码为你完成工作,这样你就可以调用一个方法并获得你想要的结果:

    您可以从文本框继承并添加一些功能,这些功能将具有文本框的所有特征,但也可以将自身添加到跟踪所有这些对象的单个列表中:

     public class CustomTextBox :TextBox
    {
        private static List<CustomTextBox> CustomTextBoxList = new List<CustomTextBox>();
    
        public static async void ValidateAll()
        {
            foreach (CustomTextBox MyCustomTextBox in CustomTextBoxList)
            {
                ****PERFORM VALIDATION****
            }
        }
    
        public CustomTextBox ()
        {
            CustomTextBoxList.Add(this);
        }
    
        ~CustomTextBox()
        {
            CustomTextBoxList.Remove(this);
        }
    }
    

    将这些添加到您的 XAML 页面非常容易(抱歉,我不确定如何将 XAML 放入这些答案中):

    Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
      StackPanel
         local:CustomTextBox Text="A" Width="150" Margin="10"/
         local:CustomTextBox Text="B" Width="150" Margin="10"/
         local:CustomTextBox Text="C" Width="150" Margin="10"/
         local:CustomTextBox Text="D" Width="150" Margin="10"/
         local:CustomTextBox Text="E" Width="150" Margin="10"/
         Button Content="Validate TextBoxes!" Click="Button_Click"/
      /StackPanel
    /Grid
    

    当您单击按钮时,它会调用一个函数,该函数将同时对所有这些执行验证:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
       CustomTextBox.ValidateAll();
    }
    

    【讨论】:

      猜你喜欢
      • 2015-09-24
      • 1970-01-01
      • 1970-01-01
      • 2018-10-08
      • 1970-01-01
      • 2014-01-09
      • 2021-01-10
      • 2020-11-06
      • 1970-01-01
      相关资源
      最近更新 更多