1

我有地址簿应用程序,并想将最终结果写入文本文件。我很难将我的列表转换为数组,以便我可以执行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); // <---- :(
    }
}
4

3 回答 3

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);
}

或覆盖ToStringPhoneBookCore使用它:

public string Save(Group g)
{
    string[] arr = g.elementsList.Select(x => x.ToString()).ToArray();
    System.IO.File.WriteAllLines(Path,arr);
}

最后,您实际上可以ToArray完全放弃调用,因为存在WriteAllLines接受 a的重载IEnumerable<string>

public string Save(Group g)
{
    System.IO.File.WriteAllLines(Path, g.elementsList.Select(x => x.ToString()));
}
于 2013-02-05T08:17:50.097 回答
3

您的代码在许多方面存在缺陷,但我现在将重点关注您的具体问题。

首先,您必须覆盖ContectToString()类中的方法:

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); } }

而且您将不再有“空异常”。请注意,我使公共属性返回列表的副本,以便调用代码无法更改您的私有成员。

于 2013-02-05T08:23:42.487 回答
1

1)如果Add方法不是所有派生类的要求,请将其声明为virtual而不是abstract

2)覆盖ToString()你的Contect班级。如果有必要,PhoneBookCore也覆盖 for。在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和。ContectContact

好的,以下是代码的完成(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
    }
}
于 2013-02-05T09:30:25.350 回答