对于对象,我有一个基本的块:当你创建一个“新”对象时,它取代了前一个对象。如果这是真的,那么在哪里创建一个对象,以便它不会在重复调用中被替换,例如while或For循环?
我正在阅读一本C#书,并尝试使用多维数组作为我的表创建一个地址簿。我的问题是每次我创建“新”数组时,先前的数据都会丢失......: - (
如果我将地址簿对象移动到另一个位置,则程序的其余部分找不到它。所有关于面向对象设计的书籍让我感到困惑和沮丧。希望你能在我的思考中揭示出错的地方。 这是我的计划:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
class Addressbook
{
public string[,] fullname;
public int cnt;
}
namespace ConsoleApp
{
class MethodParams
{
public static void Main()
{
string myChoice;
MethodParams mp = new MethodParams();
do
{
// show menu and get input from user
myChoice = mp.getChoice();
// Make a decision based on the user's choice
mp.makeDecision(myChoice);
// Pause to allow the user to see the results
Console.Write("press Enter key to continue...");
Console.ReadLine();
Console.WriteLine();
} while (myChoice != "Q" && myChoice != "q"); // Keep going until the user wants to quit
}
//*******************
// show menu and get user's choice
string getChoice()
{
string myChoice;
// Print A Menu
Console.WriteLine("My Address Book\n");
Console.WriteLine("A - Add New Address");
Console.WriteLine("D - Delete Address");
Console.WriteLine("M - Modify Address");
Console.WriteLine("V - View Addresses");
Console.WriteLine("Q - Quit\n");
Console.WriteLine("Choice (A,D,M,V,or Q): ");
// Retrieve the user's choice
myChoice = Console.ReadLine();
return myChoice;
}
//***********************
// make decision
void makeDecision(string myChoice)
{
Addressbook addrBk = new Addressbook(); //Create Addressbook Object
addrBk.fullname = new string[10, 10];
addrBk.fullname[0, 0] = "Tom";
addrBk.fullname[0, 1] = "Nesler";
addrBk.cnt = 1;
switch (myChoice)
{
case "A":
case "a":
Console.WriteLine("Enter First name");
String FName;
FName = Console.ReadLine();
Console.WriteLine("Enter Last name");
String LName;
LName = Console.ReadLine();
addrBk.fullname[addrBk.cnt,0] = FName;
addrBk.fullname[addrBk.cnt,1] = LName;
this.addAddress(ref addrBk); //Input address name
addrBk.cnt = addrBk.cnt + 1;
break;
case "V":
case "v":
this.viewAddresses(ref addrBk);
break;
case "Q":
case "q":
Console.WriteLine("Bye.");
break;
default:
Console.WriteLine("{0} is not a valid choice", myChoice);
break;
}
}
//*****************
// insert an address
void addAddress(ref Addressbook addrBk) //Addr Object containing name and Address
{
Console.WriteLine("Name: {0} {1} added.", addrBk.fullname[addrBk.cnt, 0], addrBk.fullname[addrBk.cnt, 1]);
}
//*****************
// show addresses
void viewAddresses(ref Addressbook addrBk)
{
Console.WriteLine("count is: {0}", addrBk.cnt);
for (int i=0; i < addrBk.cnt; i++)
{
Console.WriteLine("counter = {0}",i );
Console.WriteLine("Name: {0} {1} ", addrBk.fullname[i,0], addrBk.fullname[i,1] );
}
}
}
}
答案 0 :(得分:0)
string a; // this is a declaration - the variable `a` is null/nothing until
// you assign it a value
a = new String("Hello world"); // the variable `a` now references a String
// Object that contains the string "Hello world"
a = new String("Good-bye World"); // the variable `a` now references a String
// Object that contains the string "Good-bye World"
这是输掉对象的示例。在过去的旧时代&#34;这被称为内存泄漏。在今天的托管代码世界中,丢失的对象被&#34;垃圾收集&#34;
选中当您实例化和对象时,通常会将其传递给某些类似对象的集合以供以后参考。可能是列表(地址)或字典(字符串,地址)。这就是对象生活的地方。直到收集本身超出范围。
在程序内部,所有这些代码的生命周期都是有限的,即代码的运行时间。程序结束时,这是对象生命周期的最终范围。这就是为什么我们有像数据库这样的东西,所以我们可以保存和恢复我们用编程语言创建的想法
答案 1 :(得分:0)
我假设你想要创建addrBk然后更新,所以 您的示例中有几个选项。首先,您可以在Main方法中创建对象,然后将其传递给makeDecision方法:
public static void Main()
{
///...
Addressbook addrBk = new Addressbook();
addrBk.fullname = new string[10, 10];
addrBk.fullname[0, 0] = "Tom";
addrBk.fullname[0, 1] = "Nesler";
addrBk.cnt = 1;
do
{
// rest of code
mp.makeDecision(addrBk, myChoice);
// rest of code
} //while ...
}
void makeDecision(Addressbook addrBk, string myChoice)
{
switch (myChoice)
//rest of code...
}
您还可以在类中创建静态对象,然后在示例中使用它,您可能不需要创建多个对象。 检查其他fnostro答案,因为它可能会让您更深入地了解基础知识。
答案 2 :(得分:0)
每次调用makeDecision()函数时,您都会创建一个新的Addressbook对象。此外,您保留到Addressbook对象的唯一引用是通过此函数中的局部变量(addrBk)。因此,当makeDecision函数退出时,您的代码将无法再找到通讯簿。
至于这一特定代码的解决方案......有几种解决方案。最快的解决方案(但不一定总体上最干净)是获取makeDecision()函数的前5行并将它们放在Main()函数的开头。然后,每次调用时,只需将addrBk变量作为参数传递给makeDecision()函数。
答案 3 :(得分:0)
您可能会感到困惑的一件事与成员变量有关。其中一个基本思想是对象将其操作的数据与方法一起封装。这意味着,该数据可用于对象中的所有方法,并且不必作为方法的参数提供。此数据存储在成员变量中。
根据您的AddressBook
示例,您可以看到它只包含数据成员(fullname
和cnt
),但没有方法。尽管如此,您的程序仍会在地址簿上执行多项操作,例如addAddress
为其添加地址,viewAddresses
显示控制台上地址簿中的所有地址。
类的典型特征是它包含数据和方法。所以在你的情况下(只是移动你现有的一些代码,并将一些惯用的c#tweeks应用于命名):
public class Addressbook
{
private string[,] _fullname;
private int _cnt;
public Addressbook()
{
// Questions:
// Are 10 fields really needed for firstName and lastName?
// What if a user adds more than 10 names.
_fullname = new string[10, 10];
}
public void AddAddress(string firstName, string lastName)
{
_fullname[_cnt,0] = firstName;
_fullname[_cnt,1] = lastName;
Console.WriteLine("Name: {0} {1} added.", _fullname[_cnt, 0], _fullname[_cnt, 1]);
_cnt = _cnt + 1;
}
public void ViewAddresses()
{
Console.WriteLine("count is: {0}", _cnt);
for (int i=0; i < _cnt; i++)
{
Console.WriteLine("counter = {0}",i );
Console.WriteLine("Name: {0} {1} ", _fullname[i,0], _fullname[i,1] );
}
}
}
AddressBook
课程现在可以做任何事情,现在MethodParams
可以使用它而不知道AddressBook
完全 。它只需要知道可以做什么。
现在,如果我们稍微更改class MethodParams
以便我们可以为其提供一个地址簿,那么事情就变得容易了:
class MethodParams
{
private AddressBook _addressBook;
public MethodParams(AddressBook addressBook)
{
_addressBook = addressBook; // this is the address book we will work with
}
public static void Main()
{
string myChoice;
AddressBook theAddressBook = new AddressBook();
MethodParams mp = new MethodParams(theAddressBook);
do
{
// ... this can all stay the same.
} while (myChoice != "Q" && myChoice != "q"); // Keep going until the user wants to quit
// When we get here, theAddressBook still contains everything.
// We could save it to a file.
}
// ... see remarks for changes below.
}
现在,在makeDecision
方法中,您可以执行以下操作,添加地址:
_addressBook.AddAddress(FName, LName);
这是为了查看所有地址。
_addressBook.ViewAddresses();
我希望这有助于澄清一些事情。以下是评论中对您的问题的一些答案:
这一行public class Addressbook
开始定义类,这是类型,就像string
是一种类型一样。
此行private AddressBook _addressBook;
声明名为_addressBook
的私有成员变量,其类型为AddressBook
且属于类MethodParams
。< / p>
在这一行AddressBook theAddressBook = new AddressBook();
中,我们创建了一个类型为AddressBook
的新对象实例,并将其分配给名为theAddressBook
的本地变量。
在这一行MethodParams mp = new MethodParams(theAddressBook);
中,我们创建了一个MethodParams
类型的新对象实例,并通过其构造函数方法public MethodParams(AddressBook addressBook)
对其进行初始化,并将其传递给名为theAddressBook
的对象实例作为名为addressBook
的方法参数的方法参数。
在这一行_addressBook = addressBook
中,作为addressBook
提供给构造函数的值(它是我们在此代码中先前创建的theAddressBook
对象实例的引用)被分配给名为_addressBook
的私有成员变量。现在MethodParams
中的任何方法都使用_addressBook
,例如像这样_addressBook.AddAddress(FName, LName)
他们正在使用我们创建的对象实例theAddressBook
。