简体   繁体   中英

Implementation non-generic IEnumerable from mother class

I would like to ask the experts on a problem I am facing. On a bottom-up approach, I have a class StandardAccount, initialized with a couple of simple properties, one of which is enum (and a GUID which is setup automatically upon instantiation, like

public class StandardAccount
{
    private Guid _id;
    private string _accName;
    private AccountType _accType;
    private double _balance = 0;
    public enum AccountType
    {
        [Description("Asset")]
        AT,
        [Description("Liability")]
        LY,
        [Description("Profit")]
        PT,
        [Description("Loss")]
        LS
    }

    public StandardAccount(string name, AccountType type)
    {
        this._id = Guid.NewGuid();
        this._accName = name;
        this._accType = type;
        this.Balance = 0;
    }
    public double Balance { get => _balance; set => _balance = value; }
}

A Book class, must have one or more lists of those StandardAccounts and an Accounting class must have many Books. I prepare my Book class in a way to be searchable (will have many lists of StandardAccount and I need to be able to find a StandardAccount by GUID later on in those lists). I setup my Book class as follows:

public class Book
{
    private string _bookName;
    private short _bookNum;
    private Guid _bookId;

    public List<StandardAccount> Accounts { get; set; }
    public IEnumerator<StandardAccount> GetEnumerator() => Accounts.GetEnumerator();

    //compile time err: containing type does not implement interface 'IEnumerable'
    IEnumerator IEnumerable.GetEnumerator() => Accounts.GetEnumerator();
    
    //updated
    public void Add(string name, StandardAccount.AccountType type) => Accounts.Add(new StandardAccount(name, type));

    public Book(Guid? id, short BookNumber, string BookName, IEnumerable<StandardAccount> Account)
    {
        this._bookId = id ?? Guid.NewGuid();
        this._bookNum = BookNumber;
        this._bookName = BookName;
        this.Accounts = new List<StandardAccount>();
    }
    public Guid id { get => _bookId; set => _bookId = value; }
}

I have these two errors that doesn't let me go forward and I don't understand them (as I am trying to implement the enumerator in the 'mother' Book class and not in StandardAccount) Could someone please help and advise?

Note:

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;

I am trying to do this:

//this works fine
StandardAccount stdAccount = new StandardAccount("account one", StandardAccount.AccountType.AT);
//this workds fine
stdAccount.Balance = 123;

//but.. cannot add the account to my book
//ERROR - System.NullReferenceException: 'Object reference not set to an instance of an object.'
myAccounting.Book.Accounts.Add(stdAccount);
//compile time err: containing type does not implement interface 'IEnumerable'
IEnumerator IEnumerable.GetEnumerator() => Accounts.GetEnumerator();

This means you are using an explicit interface implementation . However, the book class does not implement the IEnumerable interface, so this causes an error.

Solution would be to either implement the interface

public class Book : IEnumerable

Or remove the explicit part. Note that this require a namechange since you already have a method with the same signature.

public IEnumerator GetNonGenericEnumerator() => Accounts.GetEnumerator();

However as mentioned in the comments. This is probably not a good approach to the problem. Ie you should use composition instead of inheritance, ie "a book has a list of accounts", not "a book is a list of accounts".

It is not obvious from the question exactly what you want to search for and what result you expect. If you want to search for a book what has an account with a specific id you could use:

myBooks.Where(b => b.Accounts.Any(a => a.Id == idToSearchFor));

but you would need to make the Id public. If you want the actual accounts returned instead you could use:

myBooks.SelectMany(b => b.Accounts).Where(a => a.Id == idToSearchFor);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM