Reputation: 133
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
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
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
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
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
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