WillzSawyer
WillzSawyer

Reputation: 133

Unable to access method of child classes from a List<T> of base class.

I'm creating a list of class "Task" in a way such as this.

List<Task> toDoList = new List<Task>;

Task is a base class and have designed it as such:

 public class Task : IDetail
{
    string _taskName;            //Task title.
    string _taskDescription;     //Task description.

    public Task(string tn, string td) //Constructor.
    {
        _taskName = tn;
        _taskDescription = td;
    }

    // Method set or return _taskName.
    public string taskName
    {
        get
        {
            return _taskName;
        }

        set
        {
            _taskName = value;
        }
    }

    //Method to set or return _taskDescription.
    public string taskDescription
    {
        get
        {
            return _taskDescription;
        }

        set
        {
            _taskDescription = value;
        }
    }

    public virtual void editList()
    {
        Creator editCreator = new Creator();
        editCreator.Show();
    }


}

What i've been trying todo is call methods that exists within the inherited class like one the one i have designate "Note" and have defined it as follows.

class Note : Task, IDetail
{
    string _noteDescription;

    public Note(string nd, string tn, string td)    //Constructor.
        : base(tn, td)
    {
        _noteDescription = nd;
    }

    //Method to set or return _noteDescription.
    public string noteDescription
    {
        get
        {
            return _noteDescription;
        }

        set
        {
            _noteDescription = value;
        }
    }

    public override void editList()
    {
        noteBuilder editNote = new noteBuilder();
        editNote.Show();
    }
}

However when i try to call a method of the inherited task on the list i get an error. I am trying to access the method as such:

toDoList.ElementAt(x).noteDescription;

My question is how do i prevent an error from occurring?

the error states

'toDoList.Task' does not contain a definition for 'noteDescription' and no extension method etc etc.

Should i perhaps be declaring the base class as Abstract? or is there something else i am missing?

Many thanks in advance

Upvotes: 0

Views: 591

Answers (5)

Ethan Brown
Ethan Brown

Reputation: 27282

toDoList contains Task elements, not Note elements. Now a Note element is a type of Task element, sure, but polymorphism only works in one direction: you can treat a subclass like its superclass, but you can't treat a superclass like a subclass without casting it first.

If you think about it, you'll realize that it has to be that way. What if you had a second subclass of Task called Foo: you can put both of those types in toDoList...if you tried to access noteDescription on an object that is of type Foo, you'd be in trouble.

However, there is a way to do what you want, it just requires a cast:

var note = toDoList.ElementAt(x) as Note;
var noteDescription = note==null ? "<not a note>" : note.noteDescription;

The other way to do it, of course, would be to move noteDescription into Todo, where it would be accessible from any subclass of Todo, but that's probably not what you want since the name implies that it belongs to Note.

Upvotes: 0

Shyju
Shyju

Reputation: 218832

notDescription is a property you have for your derived class. But here you are creating a list of your base class

List<Task> toDoList = new List<Task>;

You can not get the properties of derived class in a base class. IT works the other way. You can access the properties of base class in your child class.

Upvotes: 0

Chuck Savage
Chuck Savage

Reputation: 11955

Filter the list and convert them to notes, like:

var noteList = toDoList.Where(x => x is Note)
                       .Select(x => (Note)x)
                       .ToList();

then write

noteList.ElementAt(x).noteDescription;

Upvotes: 1

Kyle Trauberman
Kyle Trauberman

Reputation: 25694

Because Your list is a list of Task objects, not Note objects.

You'll need to cast your objects to Note objects before you can call methods of the Note class.

(toDoList.ElementAt(x) as Note).noteDescription;

or

toDoList.Cast<Note>().ElementAt(x).noteDescription;

The second option requires all objects in the list be Note objects.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1502186

You've got a List<Task>. That could contain any kind of Task reference - e.g. a different derived type, not a Note. Either you want a List<Note> (so it can all be type-safe), or you'll need to cast the element of the list to Note:

Note note = (Note) toDoList[x];
string description = note.noteDescription;

(Given that you've got a List<T>, you don't need to use ElementAt - use the indexer.)

Upvotes: 7

Related Questions