我有addres book app,并希望将最终结果写入文本文件。我很难将列表转换为数组,以便我可以执行WriteAllLines
命令。
接口:
abstract class PhoneBookCore {
protected string _group;
public PhoneBookCore(string group) {
this._group=group;
}
public abstract void Add(PhoneBookCore d);
}
class Contect: PhoneBookCore {
private string _firstName;
private string _lastName;
private string _phoneNumber;
private string _addres;
public Contect(string group, string firstName, string lastName, string phoneNumber, string addres)
: base(group) {
this._firstName=firstName;
this._addres=addres;
this._lastName=lastName;
this._phoneNumber=phoneNumber;
}
}
class Group: PhoneBookCore {
private List<PhoneBookCore> elements=new List<PhoneBookCore>();
public List<PhoneBookCore> elementsList {
get;
set;
}
public Group(string name)
: base(name) {
}
public override void Add(PhoneBookCore d) {
elements.Add(d);
}
}
这就是我坚持的地方
class DataOptins {
public string Save(Group g) {
foreach(var item in g) {
string[] arr=g.elementsList.ToArray(); // <---- :(
}
System.IO.File.WriteAllLines(Path, arr); // <---- :(
}
}
答案 0 :(得分:3)
不要foreach
。只需在列表中拨打ToArray
即可。但是,在执行此操作之前,您需要在组的元素中选择实际的字符串属性。
Group.elementsList
是PhoneBookCore
个对象的列表。你无法将它们转换为string
- 至少不是你班级目前的样子。因此,要么选择您真正想要的字符串属性:
public string Save(Group g)
{
string[] arr = g.elementsList.Select(x => x.StringProperty).ToArray();
System.IO.File.WriteAllLines(Path,arr);
}
或覆盖ToString
中的PhoneBookCore
并使用:
public string Save(Group g)
{
string[] arr = g.elementsList.Select(x => x.ToString()).ToArray();
System.IO.File.WriteAllLines(Path,arr);
}
最后,您实际上可以完全放弃对ToArray
的调用,因为存在WriteAllLines
的重载,它接受IEnumerable<string>
:
public string Save(Group g)
{
System.IO.File.WriteAllLines(Path, g.elementsList.Select(x => x.ToString()));
}
答案 1 :(得分:3)
您的代码在很多方面存在缺陷,但我现在将专注于您的具体问题。
首先,您必须覆盖课程 Contect 中的ToString()
方法:
public override string ToString()
{
return string.Format("{0}{1}{2}{1}{3}{1}{4}", _firstName, "\t", _lastName, _phoneNumber, _addres);
}
(这只是一个例子,当然有你自己的格式)
现在有了这样的代码来将列表变成字符串数组:
public string Save(Group g)
{
string[] lines = g.elementsList.ConvertAll(p => p.ToString()).ToArray();
System.IO.File.WriteAllLines(Path, lines );
}
现在使用此代码并使用当前代码,您将收到异常,因为g.elementsList
始终为 null 。为什么?因为你永远不会分配它。拥有其他私有成员都很好,但编译器无法知道当您致电elementsList
时,您实际上想要私人成员elements
。
将代码更改为:
private List<PhoneBookCore> elements = new List<PhoneBookCore>();
public List<PhoneBookCore> elementsList { get { return new List<PhoneBookCore>(elements); } }
你不会再有“null exception”了。请注意,我使公共属性返回列表的副本,以便调用代码将无法更改您的私有成员。
答案 2 :(得分:1)
1)如果Add
方法不是所有派生类的要求,而是将其声明为虚拟而不是抽象。
2)覆盖ToString()
课程的Contect
。如果有必要,也可以覆盖PhoneBookCore
。在Contect
类中,它将是:
public override String ToString() {
return
(new[] { _firstName, _lastName, _phoneNumber, _addres }).Aggregate((a, b) => a+"\t"+b);
}
汇总它们的规则取决于您的要求。
3)使Group
类实现IEnumerable<String>
对语义有意义,因此您不需要公开elementsList
。您需要为此实现GetEnumerator()
,但这很简单:
partial class Group: PhoneBookCore, IEnumerable<String> {
IEnumerator IEnumerable.GetEnumerator() {
return this.GetEnumerator();
}
public IEnumerator<String> GetEnumerator() {
return elements.Select(x => x.ToString()).GetEnumerator();
}
}
当您完成所有这三件事后,您就可以简单地实施Save
方法,如:
public string Save(Group g) {
string[] arr=g.ToArray(); // <---- :(
System.IO.File.WriteAllLines(Path, arr); // <---- :(
// notice: you did not show what to return in original code
}
4)建议将您的班级名称DataOptins
更改为DataOptions
,将Contect
更改为Contact
。
好的,以下是代码的完成(Save
返回的除外):
abstract class PhoneBookCore {
protected string _group;
public PhoneBookCore(string group) {
this._group=group;
}
public virtual void Add(PhoneBookCore d) {
}
}
class Contect: PhoneBookCore {
private string _firstName;
private string _lastName;
private string _phoneNumber;
private string _addres;
public override String ToString() {
return
(new[] { _firstName, _lastName, _phoneNumber, _addres }).Aggregate((a, b) => a+"\t"+b);
}
public Contect(string group, string firstName, string lastName, string phoneNumber, string addres)
: base(group) {
this._firstName=firstName;
this._addres=addres;
this._lastName=lastName;
this._phoneNumber=phoneNumber;
}
}
class Group: PhoneBookCore, IEnumerable<String> {
IEnumerator IEnumerable.GetEnumerator() {
return this.GetEnumerator();
}
public IEnumerator<String> GetEnumerator() {
return elements.Select(x => x.ToString()).GetEnumerator();
}
private List<PhoneBookCore> elements=new List<PhoneBookCore>();
public List<PhoneBookCore> elementsList {
get;
set;
}
public Group(string name)
: base(name) {
}
public override void Add(PhoneBookCore d) {
elements.Add(d);
}
}
class DataOptins {
public string Save(Group g) {
string[] arr=g.ToArray(); // <---- :(
System.IO.File.WriteAllLines(Path, arr); // <---- :(
// notice: you did not show what to return in original code
}
}