转换为数组

时间:2013-02-05 08:15:39

标签: c# text-files

我有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); // <---- :(
    }
}

3 个答案:

答案 0 :(得分:3)

不要foreach。只需在列表中拨打ToArray即可。但是,在执行此操作之前,您需要在组的元素中选择实际的字符串属性。 Group.elementsListPhoneBookCore个对象的列表。你无法将它们转换为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
    }
}