【问题标题】:How to set class values in an array of class如何在类数组中设置类值
【发布时间】:2014-11-22 15:09:15
【问题描述】:

我正在使用 Visual Studio 创建一个 Windows 窗体 C# 项目,并尝试设置一个类型类的数组,并使数组中的条目对应于该类的构造函数字符串。我正在使用一个带有变量索引的数组,每次将一个新的类实例添加到数组中时它都会增加。

我遇到了索引调用超出数组范围的问题。此外,我不确定是否为每个实例设置了我的类变量。谁能指出我正确的方向?以下是我的代码:

public partial class MainMenu : Form
{
    //int that will be used to alter the index of the array
    public static int acctcount = 1;
    //array of class Account
    Account[] accounts = new Account[acctcount];
    public MainMenu()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        //check through each element of the array
        for (int i = 0; i < accounts.Length; i++)
        {
            string stringToCheck = textBox1.Text;
            foreach(Account x in accounts)
            {
                //check to see if entered name matches any element in the array
                if (x.Name == stringToCheck)
                {
                    //set variables in another form so that we are using the class variables for only that class
                    Variables1.selectedAccount = x.Name;
                    //is this calling the CheckBalance of the instance?
                    Variables1.selectedCheckBalance = Account.CheckBalance;
                    //same thing?
                    Variables1.selectedSaveBalance = Account.SaveBalance;

                    //switch to form
                    AccountMenu acctMenu = new AccountMenu();
                    this.Hide();
                    acctMenu.Show();
                }
                else
                {
                    /*insert new instance of Account
                    the index element should be 0, since acctcount is set to 1
                    and we are subtracting 1 from the acctcount
                     we are using the string from the textbox1.Text as the constructor
                     for the new instance*/
                    accounts [acctcount-1] = new Account(stringToCheck);
                    //increase the index of the array by 1
                    acctcount += 1;
                }
            }
        }
    }

}
class Account
{
    private string name;
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
        }
    }
    private static int acctNum = 0;
    public static int AcctNumber
    {
        get
        {
            return acctNum;
        }
        set
        {
            acctNum = value;
        }
    }
    //initialize the CheckBalance value to 100.00
    private static decimal checkBalance = 100.00M;
    public static decimal CheckBalance
    {
        get
        {
            return checkBalance;
        }
        set
        {
            checkBalance = value;
        }
    }
    public Account(string Name)
    {
        this.Name = Name;
    }
    private static decimal saveBalance = 100.00M;
    public static decimal SaveBalance
    {
        get
        {
            return saveBalance;
        }
        set
        {
            saveBalance = value;
        }
    }
}

【问题讨论】:

  • 另外,您可能希望Account 类的属性是实例属性而不是静态属性...
  • 您使用数组而不是列表是否有原因?

标签: c# arrays indexoutofboundsexception


【解决方案1】:

报告异常的问题[最有可能] 是accounts[acctcount-1] 行,因为当acctcount >= 2(例如accounts[1])时,它将引发 IndexOutOfBounds 异常,就像在第一次单击按钮后发生的那样acctcount 的增量。然而,数组只有只有一个元素,因为它是使用accounts = new Account[acctcount]; 创建的 - C# 中的数组不会增长/调整大小

最简单和最好的直接解决方法是使用List(参见Collections (C#))而不是数组;列表可以动态增长。那么代码就变成了:

// (remove the "acctcount" field as it is no longer useful)
List<Account> accounts = new List<Account>();
// ..
accounts.Add(new Account(stringToCheck));

正如 Trevor 所指出的,删除 Accounts 类中的static modifier;否则成员数据将被错误地共享(即每个帐户将具有相同的余额!)并相互“覆盖”。如果使用静态是试图从表单中“传回”数据,请参阅How to return a value from a Form in C#? 以获得更可行的解决方案。公共属性的相同用途可用于将(帐户)对象传入表单。

【讨论】:

  • 谢谢。切换到列表是有意义的。或者,不能使用 array.Resize 来代替吗?对于静态修饰符,我使用它来设置 Variables1 属性。不过我明白你在说什么。如何根据数组元素访问实例的变量?
  • @JustinDay Arrays.Resize 创建一个 new 数组。它使用ref 关键字重新分配作为输入提供的变量。我不建议在这里使用这种方法,尽管数组有一些用例。
  • @JustinDay 就可以访问数据而言,提供要修改的 actual Account 对象。比如在表单中修改账户信息就有了一个公共的Account属性。将此设置为帐户以在显示表单之前修改 ,然后从表单中修改 该对象(分配给表单的 Account 属性)。
  • @JustinDay 为了使代码更简洁,删除当前 Click 处理程序中的循环并创建一个名为 Account FindByName(string name) 的方法。找到那里的帐户,如果它存在,则返回它(如果不存在,则返回 null)。
【解决方案2】:

多次单击按钮时会引发异常。

您创建了一个大小为 1 的数组,当您第二次单击该按钮并尝试在索引 2 处添加一个元素时,该索引已超出范围。

当您添加新项目时,数组的大小不会增加。

正如所指出的,你应该使用一个集合,比如List&lt;T&gt;

如果你想继续使用数组,每次添加新元素时,都需要创建一个更大的新数组,将旧数组的元素复制到新数组,并将旧数组引用到新数组.您还可以创建一个更大的数组,并且仅在它已满时创建一个新数组。这基本上是 .Net 集合已经实现的。

与往常一样,这完全取决于您的需求和要求。

【讨论】:

    猜你喜欢
    • 2020-01-14
    • 2017-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    相关资源
    最近更新 更多