Reputation: 12192
Ok, we have the class Ticket that contains a property:
List<TaskComment> Comments;
I have it set up with a back property so that I can do some validation:
private List<TaskComment> _comments;
public List<TaskComment> Comment
{
get
{ //stuff }
internal set
{ //stuff }
}
Despite setting the set to internal, the Add() method is still exposed outside of the assembly. But regardless, what I want to do is set the ticketId property of a comment object as it is being added to the collection. For example:
var ticket = new TaskTicket();
var comment = new TaskComment { //initializers }
ticket.Comments.Add(comment);
--inside the ticket:
public List<TaskComment> Comments
{
get{ //stuff }
set
{
((TaskComment)value).TicketId = this._ticketId;
}
}
But this isn't working. It's telling me that it can't cast from TaskComment to MyLibrary.TaskComment. Which really doesn't make any sense to me. But besides that, this doesn't feel right anyway. So how exactly do I modify the incoming value/object before adding it to the class's collection?
Upvotes: 0
Views: 181
Reputation: 6791
Keep the private field as a List, but change your property so that it's readonly and is IEnumerable. Then implement a specific Add method, as others have suggested, that accesses the private field. This way your callers can freely iterate over the collection but must use the add method to add to it, giving you a place to validate, etc and throw exceptions or return a success code.
Returning concrete collection types limits your options for future changes. Whereas, returning an interface allows you to change the underlying collection with no impact on the caller(s).
Newing up a ReadOnlyCollection seems wasteful when a List has implicit IEnumerable support.
Upvotes: 0
Reputation: 35409
Expose the Collection
as readonly:
public IReadOnlyCollection<TaskComment> Comments
{
get { return new ReadOnlyCollection(_comments); }
}
Using the previous implementation _comments
is now exposed to the caller. To allow the client to add/remove items you'd implement Add
and Remove
members that add\remove from the internal list.
public void Add(Comment comment)
{
/* code */
_comments.Add(comment);
}
public void Remove(Comment comment)
{
/* code */
_comments.Remove(comment);
}
Alternatively, you could implement your own IList
providing the proper implementations for your Add
and Remove
methods.
Upvotes: 5
Reputation: 62256
There is no way you can limit pubblicly esposed List<T>
class.
If you don't use the ponetial of the List<T>
in your app too much, I would suggest to just wrap that list.
Say:
pulbic void AddComment(TaskComment task)
{
/*Some validation on task parameter*/
taskComments.Add(task);
}
and remove public get
acessor from the Comments
property, or entire property itself (*if this is possible)
Upvotes: 0
Reputation: 9279
The value object in your setter is going to be of type List so when you cast it to type TaskComment, it is throwing the error. In your code you could just do
var comment = new TaskComment { //initializers }
comment.TicketId = ticket.TicketId; //where TicketId is a public property for _ticketId
ticket.Comments.Add(comment);
Or you could overload the Add() method to add the comment to the Comment collection
Upvotes: 0