为啥我的 C# 数组在没有分配任何内容的情况下发生变化?
Posted
技术标签:
【中文标题】为啥我的 C# 数组在没有分配任何内容的情况下发生变化?【英文标题】:Why is my C# Array changing without anything being assigned to it?为什么我的 C# 数组在没有分配任何内容的情况下发生变化? 【发布时间】:2020-06-29 18:27:03 【问题描述】:我有一个小型 winforms 程序,用于创建食谱书。该应用程序有两个窗口,但我的错误只与一个有关。
我有两个主要的类:Recipe.cs 和RecipeManager.cs,其想法是RecipeManager 包含一个Recipes 数组。 (对于这个任务,我们不允许使用 Linq 或 ArrayLists)
现在,当我填写表格并单击“添加配方”时,第一个成功运行并且列表框正确填充,但是第二次“添加配方”recipeList
数组似乎被新的完全食谱,我不知道为什么会这样。 recipeList
似乎在我的 Add
方法甚至将它添加到数组之前发生了变化!
查看相关问题的 gif:
https://i.imgur.com/sIMICcG.gifv
食谱.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace programmingTask4
public class Recipe
private string[] ingredientArray;
private string name;
private FoodCategory category;
private string description;
private const int maxNumOfIngredients = 20;
public string Name
get return name;
set name = value;
public FoodCategory Category
get return category;
set category = value;
public string Description
get return description;
set description = value;
public string[] Ingredient
get return ingredientArray;
set ingredientArray = value;
public int MaxNumOfIngredients
get return ingredientArray.Length;
public Recipe(int maxNumOfIngredients)
Console.WriteLine("Recipe constructor was called!");
ingredientArray = new string[maxNumOfIngredients];
DefaultValues();
public void DefaultValues()
for (int i = 0; i < ingredientArray.Length; i++)
ingredientArray[i] = string.Empty;
name = string.Empty;
category = FoodCategory.Vegetarian;
description = string.Empty;
public int FindVacantPosition()
int results;
for (int i = 0; i < ingredientArray.Length; i++)
if(ingredientArray[i] == string.Empty)
results = i;
return results;
return -1;
public bool AddIngredient(string value)
bool ok;
int next = FindVacantPosition();
if(next >= 0)
ok = true;
ingredientArray[next] = value;
else
ok = false ;
return ok;
public bool CheckIndex(int index)
bool check = false;
if(index <= ingredientArray.Length && index >= 0)
check = true;
return check;
public int GetCurrentNumOfIngredients()
int count = 0;
for (int i = 0; i < ingredientArray.Length; i++)
if (!string.IsNullOrEmpty(ingredientArray[i]))
count++;
return count;
public override string ToString()
int chars = Math.Min(description.Length, 15);
string descriptionText = description.Substring(0, chars);
if (string.IsNullOrEmpty(descriptionText))
descriptionText = "NO DESCRIPTION";
string textOut = string.Format("0, -20 1,4 2,-12 3,-15", name, GetCurrentNumOfIngredients(), category.ToString(), descriptionText);
return textOut;
public bool ChangeIngredientAt(int index, string value)
bool bok = true;
if (CheckIndex(index))
ingredientArray[index] = value;
else
bok = false;
return bok;
public bool DeleteIngredientAt(int index)
bool bok = true;
if (CheckIndex(index))
ingredientArray[index] = "NO DESCRIPTION";
else
bok = false;
return bok;
RecipeManager.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace programmingTask1
class RecipeManager
private Recipe[] recipeList;
public RecipeManager(int maxNumOfElements)
Console.WriteLine("Recipe manager constructor called!");
recipeList = new Recipe[maxNumOfElements];
private int FindVacantPosition()
for (int i = 0; i < recipeList.Length; i++)
if (recipeList[i] == null)
Console.WriteLine("Found free position at: " + i);
return i;
return -1;
public bool CheckIndex(int index)
bool check = false;
if (index <= recipeList.Length && index >= 0)
check = true;
return check;
public Recipe GetRecipeAt(int index)
if (CheckIndex(index))
return recipeList[index];
else
return null;
public bool Add(Recipe newRecipe)
if (newRecipe == null)
return false;
bool ok;
int next = FindVacantPosition();
if (next >= 0)
ok = true;
Console.WriteLine("Setting recipe list at index " + next + " to " + newRecipe.ToString());
recipeList[next] = newRecipe;
else
Console.WriteLine("No space for recipe available! " + next);
ok = false;
return ok;
public int CurrentNumberofItems()
int num = 0;
for (int i = 0; i < recipeList.Length; i++)
if (recipeList[i] != null)
num++;
return num;
public string[] RecipeListToString()
string[] results = new string[recipeList.Length];
for (int i = 0; i < recipeList.Length; i++)
if (recipeList[i] != null)
results[i] = recipeList[i].ToString();
else
results[i] = string.Empty;
return results;
FormMain.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace programmingTask4
public partial class FormMain : Form
const int maxRecipe = 3;
const int maxIngredients = 20;
Recipe currRecipe = new Recipe(maxIngredients);
RecipeManager recipemanager = new RecipeManager(maxRecipe);
public FormMain()
Console.WriteLine("Form constructor was called!");
InitializeComponent();
InitializeGui();
public void InitializeGui()
comboBoxCategory.DataSource = Enum.GetValues(typeof(FoodCategory));
public void UpdateGUI()
//listBoxDisplay.Text = recipemanager.CurrentNumberofItems().ToString();
//listBoxDisplay.Text = currRecipe.Ingredient.ToString();
string[] recipeListStrings = recipemanager.RecipeListToString();
listBoxDisplay.Items.Clear();
listBoxDisplay.Items.AddRange(recipeListStrings);
private void buttonRecipe_Click(object sender, EventArgs e)//add recipe button
currRecipe.Category = (FoodCategory)comboBoxCategory.SelectedIndex;
currRecipe.Name = textBoxRecipeName.Text.Trim();
currRecipe.Description = richTextBoxDescription.Text.Trim();
Console.WriteLine("Adding recipe: " + currRecipe.ToString());
bool result = recipemanager.Add(currRecipe);
Console.WriteLine("Result was " + result + " for adding to recipe list");
UpdateGUI();
currRecipe.DefaultValues();
【问题讨论】:
Using the free, built-in Step Debugger 调试代码比您想象的要容易。它还将帮助您了解代码的执行方式,从而帮助您编写更好的代码。 我在我的代码中添加了断点,然后慢慢地通过(并进入)。只要调用 Add ,但在 Add 有机会做任何事情之前,recipeList 就会发生变化。 @ŇɏssaPøngjǣrdenlarp 一方面,你让它变得比它需要的更复杂。数据绑定将简化显示方面,并且现代集合已经提供了您复制到查找和检查事物的所有功能。此外,您不会在调用 Add 的单击事件中创建新的配方项。然后更新道具的行正在更改最后一项并再次添加它 @Cherona 研究一下reference type,你会明白的。 【参考方案1】:Recipe
是一个类,这意味着它是一个 reference type.
在您的主窗体中,您的 currRecipe
实例永远不会更改。
RecipeManager
有一个数组来存储实例的引用,但不幸的是它存储了相同的实例,因为 2。
由于RecipeManager
存储了currRecipe
的同一个实例,因此对currRecipe
的任何修改都会显示N 次。
为了防止它。修改你的buttonRecipe_Click
private void buttonRecipe_Click(object sender, EventArgs e)//add recipe button
currRecipt = new Recipe(maxIngredients);
currRecipe.Category = (FoodCategory)comboBoxCategory.SelectedIndex;
currRecipe.Name = textBoxRecipeName.Text.Trim();
currRecipe.Description = richTextBoxDescription.Text.Trim();
Console.WriteLine("Adding recipe: " + currRecipe.ToString());
bool result = recipemanager.Add(currRecipe);
Console.WriteLine("Result was " + result + " for adding to recipe list");
UpdateGUI();
// No need to reset it, use new one everytime.
//currRecipe.DefaultValues();
【讨论】:
以上是关于为啥我的 C# 数组在没有分配任何内容的情况下发生变化?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 JavaScript 中显示数组元素的上限为 100,有没有办法在没有循环或 splice() 的情况下显示所有内容? [复制]