【问题标题】:C# recurring class instantiation unnecessary?C# 循环类实例化不必要吗?
【发布时间】:2015-01-10 11:13:45
【问题描述】:

我有主课:

class MainClass
{
    public static void Main()
    {
        InputForm InputForm1 = new InputForm();
        InputForm1.ShowDialog(); // show interface to prompt user
    }
}

简单地调用一个windows窗体。这有以下类:

public partial class InputForm : Form
{
    public InputForm()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e) 
    {   
        // do some calculation and then create a dictionary of items

        for (int n = 1; n <= dict.Count; n++) // loop through items
        {
            LengthClass theLength = new LengthClass();
            dict[n].calculatedLength = theLength.calcLength(arg1, arg2, dict[n].speed); 

        }
    }
}

单击按钮时,程序会对从电子表格中读取的数据进行一些计算,并将结果保存到字典中。每个元素都是一种动物,我有一些属性存储在字典中(例如,在“狗”键下,我有狗的平均重量、平均速度等)。 使用速度和两个默认参数(arg1 和 arg2),我必须调用类 LengthClass 的方法,以获取特定动物在 arg1 小时和 arg2 分钟内覆盖的估计长度。 LengthClass 是这样的:

class LengthClass
{
    public double calcLength(double arg1, double arg2, double speed)
    {
        // do some calculation
        return x;
    }
}

现在我的疑问是如何更好地设计代码。当遍历字典中的每个键时,我每次都会实例化一个 LengthClass 并调用它的方法。 这是正确的做法吗?我想将计算长度的方法与 windows 窗体中的代码分开,以便在必要时更容易更改它。但是我认为每次都实例化类可能会减慢代码的速度,而更好的设计可以使代码保持快速且易于阅读。有什么建议吗?

感谢下面的答案,似乎将方法 calcLength 声明为静态可以解决问题并避免重复实例化 LengthClass 的需要。 但是如果 LengthClass 有一个额外的方法,比如 calcLength2(),为了执行计算需要调用一个新类的方法,比如 helpClass,我是否需要将 helpClass 的方法声明为静态以避免实例化 helpClass在 LengthClass 中从我的 calcLength2() 调用它的方法时?

【问题讨论】:

  • 将方法设为静态,然后您可以直接调用LengthClass.calcLength(arg1, arg2, dict[n].speed) 而无需创建实例。
  • 您可以将 LengthClass 设为静态,但性能改进将微不足道,甚至可以忽略不计:stackoverflow.com/questions/12279438/…
  • @PhilipPittle 这可能是真的,但它不是一个很好的设计来创建一个对象来调用一个可能是静态的方法。要么让对象接受参数并将长度作为计算属性,要么只使用静态方法
  • 我同意在这种情况下静态方法是正确的design 选择。但是 OP 还询问使用实例类是否会slow down the code。性能的答案基本上是在此处创建新实例对性能的影响可以忽略不计。

标签: c# class dictionary methods


【解决方案1】:

从您给出的示例中,calcLength 方法不需要是实例方法,因为它不使用 LengthClass 的任何字段。您可以通过将此方法设为静态来完全避免或创建对象:

class LengthClass
{
    public static double calcLength(double arg1, double arg2, double speed)
    {
        // do some calculation
        return x;
    }
}

那么你可以这样称呼它:

public partial class InputForm : Form
{
    public InputForm()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e) 
    {   
        // do some calculation and then create a dictionary of items

        for (int n = 1; n <= dict.Count; n++) // loop through items
        {
            dict[n].calculatedLength = LengthClass.calcLength(arg1, arg2, dict[n].speed); 
            v = myPort[n].midVol;
        }
    }
}

【讨论】:

    【解决方案2】:

    进一步扩展 Sam Holder 的好答案,您的 LengthClass 似乎最好标记为 static 本身。感觉您不应该创建 LengthClass 的实例,尤其是因为它不包含任何持久成员。 UML guidelines 用类来描述最好的属性可能会有所帮助。

    static class LengthClass
    {
        public static double calcLength(double arg1, double arg2, double speed)
        {
            // do some calculation
            return x;
        }
    }
    

    及用法:

    private void button1_Click(object sender, EventArgs e) 
    {   
        for (int n = 1; n <= dict.Count; n++) // loop through items
        {
            dict[n].calculatedLength = LengthClass.calcLength(arg1, arg2, dict[n].speed); 
            v = myPort[n].midVol;
        }
    }
    

    另一个提示是,如果您确实需要将 LengthClass 作为对象,最好在 for 循环范围之外实例化它,尤其是在创建成本高昂的情况下。

    【讨论】:

    • 这是一个很好的观点,虽然我不确定课程的其余部分只是为了问题的简洁而被省略
    • 如果 LengthClass 还包含另一个需要实例化另一个类以使用其方法并在返回速度值之前执行计算的方法,我可以使用相同的解决方案吗?
    • @mickG:你可以这样做,但为什么要实例化不显示状态、行为和身份的东西?
    猜你喜欢
    • 2020-07-20
    • 2011-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多