In many of our projects I have seen a few custom collection / or container classes that hold a some sort of generic collection, e.g. a List(of T) class.
They usually have a GetXXX method that returns a IEnumerable of whatever type the custom collection class uses so the internal collection can be iterated around using a foreach loop.
e.g.
public IEnumerable<UploadState> GetStates
{
get
{
return new List<UploadState>(m_states);
}
}
My question is that should these classes instead implement the IEnumerable interface, and call GetEnumerator on the List itself.
Is there a preferred way, or is it up to the developer?
If your class is a custom collection class then yes, it should implement IEnumerable<T>. In this case a public property for the inner list would be redundant. Imagine a simple class:
public class People : IEnumerable<Person>
{
List<Person> persons = new List<Person>();
public IEnumerator<Person> GetEnumerator()
{
return persons.GetEnumerator();
}
}
But if your class cannot act like a collection then provide a public IEnumerable property for its elements:
public class Flight
{
List<Person> passengers = new List<Person>();
public IEnumerable<Person> Passengers
{
get { return passengers; }
}
}
Anyway, it's always up to the developer to choose the right design.
I would do it that way:
public IEnumerable<UploadState> GetStates
{
get
{
foreach (var state in m_states) {
yield return state;
}
}
}
It is cleaner, your users don't get a list where they shouldn't (they could cast it to a List<T>after all) and you don't need to create a List<T>object.
EDIT: Misunderstood the question. I think if the class is meant to be a collection, it should implement IEnumerable<T>.
Consider that in your code example a new list created. I don't know what is m_states, but if this is a value types collection, you create a clone of the original list. In this way the returning list can be manipulated form the caller Add/Remove/Update elements. without affectiing original data.
If m_states are reference types, this still creates a new list which can be again manipulated by the caller Add/Remove/ No update elements (it's a reference!) without affecting original data.
What about IEnumerable<T>, its just a way to make a returning type generic, and not make strong coupling to List<T> type.
I think if your newly implemented class just behaves the sameway as a list does, there is no need to implement it. If you need some kind of custom logic, it depends on what you want to do; you can inherit list or you can implement IEnumerable. It just depends what is to be achieved.
You might want to check this:
http://www.codeproject.com/Articles/4074/Using-IEnumerator-and-IEnumerable-in-the-NET-Frame
I didn't read fully it yet, but I think this answers your question.
You should be deriving your custom collection classes based on one of the classes in System.Collections.ObjectModel namespace. They already contain implementations of IEnumerable<T> and the non generic IEnumerable interfaces.
Related
Currently, I have a class (classB) that has a list --v
class classB
{
public List<int> alist { get; private set; }
...
And I can accessing this class from another class (classA)
ClassB foo = new ClassB();
foo.alist.Add(5);
Question is, can I stop this from happening? (make it unchangeable from other classes) Thanks!
Just expose the IReadOnlyList<T> interface:
private List<int> alist;
public IReadOnlyList<int> Alist
{
get { return this.alist; }
}
From inside of the class, you continue to use "alist", to add/remove elements. From outside of the class you can only access "Alist", which doesn't allow to modify the collection (unless explicitly cast).
Well, there are various options here.
You could change the property type to one which only provides a read-only interface (e.g. IReadOnlyList<T> or IEnumerable<T>. That doesn't stop the caller from casting the returned reference back to List<T> though.
You could create a ReadOnlyCollection<T> to wrap your real list, and only expose that - that wrapper will prevent the caller from being able to access the real list at all (other than by reflection)
If your code doesn't need to modify the collection either, you could just keep the ReadOnlyCollection<T> wrapper, or use the immutable collections package
You could avoid exposing the list at all, perhaps implementing IEnumerable<T> within your class
It really depends on exactly what your requirements are.
I canĀ“t remove an element from an IEnumerable list, but this list is a reference to a List , a private attribute of an other class.
If I put personsCollection.Remove(theElement) in the same class (class Manager), it works perfect, but I need to delete the element since the other class (class ManagerDelete). Please how can I do this?
Thanks.
class Other
{
//Some code
public IEnumerable<Person> SearchByPhone (string value)
{
return from person in personCollection
where person.SPhone == value
select person;
}
}
class ManagerDelete
{
//Some code
IEnumerable<Person> auxList= SearchByPhone (value);
//I have a method for delete here
}
class Manager
{
//Some code
private List<Person> personsCollection = new List<Person>();
}
You can't delete from an IEnumerable<T> you need to make it of type IList<T> to add/remove items directly from it.
You need to understand what an IEnumerable Interface allows you to do.
I'v listed below the list of Interfaces that you should use by design, as and when required in differnt circumstances. In your example IList is what you will need to use.
ICollection Defines general characteristics (e.g., size, enumeration,
and thread safety) for all non-generic collection types.
ICloneable Allows the implementing object to return a copy of itself
to the caller.
IDictionary Allows a non-generic collection object to represent its
contents using key/value pairs.
IEnumerable Returns an object implementing the IEnumerator interface
(see next table entry).
IEnumerator Enables foreach style iteration of collection items.
IList Provides behavior to add, remove, and index items in a
sequential list of objects.
Darren is right.
Without converting to a list you can do:
personCollection = personCollection.Except(SearchByPhone(value));
in ManagerDelete.
You can use ToList to convert the IEnumerable to a List and then you can remove stuff from it.
var auxList= SearchByPhone (value).ToList();
auxList.Remove(something);
You can cast the IEnumerable to an IList. This will work if the IEnumerable is really a List. However this is a bad design. If you want to remove items, you should expose the list as an IList, not IEnumerable.
An IEnumerable is literally just an interface to say, I've got this collection, you can iterate over it.
If you take a look at the actual details of the IEnumerable interface, it doesn't contain much, only a method to allow callers to iterate over it:
http://msdn.microsoft.com/en-gb/library/9eekhta0.aspx
The reason why List types can allow you to remove them, is it's built on top of the IEnumerable interface, giving you more functionality. It is supposed to represent a collection of objects you can manipulate. Whereas an IEnumerable is simply not designed to do this.
The Remove method actually stems from the underlying ICollection interface that List also implements:
http://msdn.microsoft.com/en-gb/library/bye7h94w.aspx
In addition to other answers: your data structure choice doesn't seem to be adequate. If you really plan to remove elements from a container, your container must not be an IEnumerable<> in the first place!
Consider the following choices:
switch from IEnumerable<> to ICollection<>;
replace removing with filtering out (.Where()) and obtaining a separate filtered IEnumerable<>.
It is said that IEnumerable is used in a custom collection. One of the uses is the foreach loop used to traverse through the custom collection.
However my question is that instead of making a custom collection that first implements IEnumerable and then constructing another class to implement IEnumerator to store a group of custom objects, why can't we just use list<your_customer_object>.
Thanks in advance for help.
Because you might want to implement a different data structure. IEnumerable abstracts the concept of sequence, while a List has the concept of index, adding/removing items and its own, data structure.
As an example of different structure, here's a class which allows you to enter an infinite foreach loop.
public class InfiniteSequence : IEnumerable<int>
{
public IEnumerator<int> GetEnumerator()
{
return new InfiniteEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
class InfiniteEnumerator : IEnumerator<int>
{
public void Dispose()
{
throw new NotImplementedException();
}
public bool MoveNext()
{
Current++;
return true;
}
public void Reset()
{
Current = 0;
}
public int Current { get; private set; }
object IEnumerator.Current
{
get { return Current; }
}
}
}
Of course you can use List<T>.
If List<T> fits your needs, then use it and don't create a new class that inherits from IEnumerable<T>.
You would provide your own implementation of IEnumerable<T> when List<T> isn't right for your needs. The canonical example of this is when you want to support lazy evaluation of your collection, perhaps with a method that uses yield return.
As #ken2k said, you can just List<T> and you will got a generic version of List with your T type. But if you want to hide this implementation and customize some operations that List<T> or include new features, you can inherits from the List and implement your own methods. For sample:
public class CustomerCollection : List<Customer> // at this time, you have all methods from List such as Add, Remove, [index] etc...
{
public double AverageAge()
{
return this.Average(customer => customer.Age)
}
// other methods...
}
IEnumeralbe is the most abstraction of collections in .Net Framework, you can just interate in this abstraction.
You can just use List<T> or any other of the generic collection types. After all List<T> implements IEnumerable<T>.
Do you have a particular edge case that you need to cover with a bespoke collection?
Of course you can define your members as List<T>, that however binds the customer of your class to a specific implementation. If you define the member as IEnumerable<T> (assuming that the consumers will only want to enumerate your collection) than you can change the implementation to a different collection type that implements the interface without breaking the contract. You if you change it from List<T> to SortedSet<T> to implement order your consumers are not affected.
It's basically the advantage of coding against interfaces rather than concrete types.
You can use a different interface, ie. ICollection<T> if your consumers want more than just enumerate.
If it doesn't do anything else, go ahead. Specialized collections are for collections that need to do... special... things.
(For example, a ListViewItemCollection would have to notify its parent ListView when updated, so it needs to implement IList(T), and therefore IEnumerable(T). If you had a custom collection, it might inherit from that. Inheriting only from IEnumerable(T) makes sense only when your collection can be enumerated, but not indexed.)
You Can.
public class List<T> : IList<T>, ICollection<T>,
IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>,
IEnumerable
I think the source of confusion here is the difference between a "custom collection" and a "collection of custom class instances". Of these two, your List<CustomObject> is the latter case - you are only reusing a collection created by someone else and taking advantage of generics to keep the item type info, that's all. Truly custom collection would probably implement IEnumerable<T>, but you will rarely (if ever) need it.
So in this case you not only can, but probably also should use List<CustomObject>
Ok so I was just working through the IEnumerator and IEnumerable. Now the MSDN says that the main objective of these things is to iterate through a customer collection.
Fair enough I was however able to iterate through a custom collection without the use of either (or at least I'd like to think so)
namespace ienumerator
{
class person
{
public person(string first, string second)
{
fname = first;
lname = second;
}
public string fname { get; set; }
public string lname { get; set; }
}
class person_list
{
public person[] list;
public person_list(person[] per)
{
list = new person[per.Length];
for (int i = 0; i < per.Length; i++)
{
list[i] = per[i];
}
}
}
class Program
{
static void Main(string[] args)
{
person[] names = new person[3]
{
new person("some","one"),
new person("another","one"),
new person("sss","ssdad"),
};
person_list list_of_names = new person_list(names);
int i = 0;
while (i < list_of_names.list.Length)
{
Console.WriteLine(list_of_names.list[i].fname);
i++;
}
Console.Read();
}
}
}
So what is flawed in my understanding, the above is giving me the same result that I achieve after implementing IEnumerator and IEnumerable.
I was however able to iterate through a custom collection without the use of either
Of course you can iterate your own collection without the interface; if you couldn't, then how would you implement the interface?
You, as a code implementor, do not implement an interface for your convenience. You implement it for the convenience of the consumer of your code. The interface means "attention customer: you can enumerate the contents of this collection without having to know anything about how I implemented it".
That's the purpose of an interface: it provides an abstraction that allows consumers of your code to use it without having to understand how it works.
In your main function you used two aspects of person_list to iterate through the list of people, Length and the [] operator for taking the member of a collection at a certain position.
However, what if you had some container or custom collection which didn't implement one or both of these? For example, a class that read a file line by line might not know in advance what the length of the collection was and so not define Length. An enumerator that reads messages from a queue might only be able to take the next one, and not one, say, four positions ahead with [4]. In both cases you can still 'iterate' through the collection properly.
IEnumerator and IEnumerable require exactly the attributes that are needed for foreach to work and no others, which is why functions can use them as requirements, knowing that they will be able to iterate through whatever type of collection they get passed.
You can of course iterate over a custom collection without implementing the IEnumerable interface, but then the iterating code has to know your custom collection.
If you implement IEnumerable, the code that iterates over all elements does not need to know your person_list class. It uses an instance of some class that implements IEnumerable, and it will still work if you exchange the actual instance for something else that also implements IEnumerable later on.
Actually, in C#, it is not required to implement the IEnumerable and IEnumerator to customize you own collections. If you iterate the collection by using traditional way that is fine for you, but it will be trouble if you use foreach to iterate the collection.
Another reason, if you want to expose your class so that VB.NET user can employ you should consider to implement the both interface.
Be note that IEnumerable is difference in non-generic and generic collection. The non-generic one belong to System.Collection the other is belong to System.Collection.Generic namespace
There is a plenty of ways to iterate over custom sequence. One way to do this is to use Iterator Design Pattern.
Iterator Pattern is used to unify traversing over custom sequence (it could be a collection in memory, generated collection or something else). In .NET world this pattern implemented in the following way: we have a iterable object that implements IEnumerable interface (and this shows to any customer of your class that you have a ability for traversing your content).
And we have a iterator itself (object that implements IEnumerator interface) that you can treat as a "pointer" to current position in your iterable object. Because you may have inner loops (i.e. multiple iterations over the same object in one time) you have to split iterable object from the iterator.
Basically there is a plenty of ways to traverse a specific sequence, but Iterator Pattern gives you an ability to "generalize" this approach hiding particular implementation of the traversing algorithm from the callers inside the implementation.
I know there has been a lot of posts on this but it still confuses me why should you pass in an interface like IList and return an interface like IList back instead of the concrete list.
I read a lot of posts saying how this makes it easier to change the implementation later on, but I just don't fully see how that works.
Say if I have this method
public class SomeClass
{
public bool IsChecked { get; set; }
}
public void LogAllChecked(IList<SomeClass> someClasses)
{
foreach (var s in someClasses)
{
if (s.IsChecked)
{
// log
}
}
}
I am not sure how using IList will help me out in the future.
How about if I am already in the method? Should I still be using IList?
public void LogAllChecked(IList<SomeClass> someClasses)
{
//why not List<string> myStrings = new List<string>()
IList<string> myStrings = new List<string>();
foreach (var s in someClasses)
{
if (s.IsChecked)
{
myStrings.Add(s.IsChecked.ToString());
}
}
}
What do I get for using IList now?
public IList<int> onlySomeInts(IList<int> myInts)
{
IList<int> store = new List<int>();
foreach (var i in myInts)
{
if (i % 2 == 0)
{
store.Add(i);
}
}
return store;
}
How about now? Is there some new implementation of a list of int's that I will need to change out?
Basically, I need to see some actual code examples of how using IList would have solved some problem over just taking List into everything.
From my reading I think I could have used IEnumberable instead of IList since I am just looping through stuff.
Edit
So I have been playing around with some of my methods on how to do this. I am still not sure about the return type(if I should make it more concrete or an interface).
public class CardFrmVm
{
public IList<TravelFeaturesVm> TravelFeaturesVm { get; set; }
public IList<WarrantyFeaturesVm> WarrantyFeaturesVm { get; set; }
public CardFrmVm()
{
WarrantyFeaturesVm = new List<WarrantyFeaturesVm>();
TravelFeaturesVm = new List<TravelFeaturesVm>();
}
}
public class WarrantyFeaturesVm : AvailableFeatureVm
{
}
public class TravelFeaturesVm : AvailableFeatureVm
{
}
public class AvailableFeatureVm
{
public Guid FeatureId { get; set; }
public bool HasFeature { get; set; }
public string Name { get; set; }
}
private IList<AvailableFeature> FillAvailableFeatures(IEnumerable<AvailableFeatureVm> avaliableFeaturesVm)
{
List<AvailableFeature> availableFeatures = new List<AvailableFeature>();
foreach (var f in avaliableFeaturesVm)
{
if (f.HasFeature)
{
// nhibernate call to Load<>()
AvailableFeature availableFeature = featureService.LoadAvaliableFeatureById(f.FeatureId);
availableFeatures.Add(availableFeature);
}
}
return availableFeatures;
}
Now I am returning IList for the simple fact that I will then add this to my domain model what has a property like this:
public virtual IList<AvailableFeature> AvailableFeatures { get; set; }
The above is an IList itself as this is what seems to be the standard to use with nhibernate. Otherwise I might have returned IEnumberable back but not sure. Still, I can't figure out what the user would 100% need(that's where returning a concrete has an advantage over).
Edit 2
I was also thinking what happens if I want to do pass by reference in my method?
private void FillAvailableFeatures(IEnumerable<AvailableFeatureVm> avaliableFeaturesVm, IList<AvailableFeature> toFill)
{
foreach (var f in avaliableFeaturesVm)
{
if (f.HasFeature)
{
// nhibernate call to Load<>()
AvailableFeature availableFeature = featureService.LoadAvaliableFeatureById(f.FeatureId);
toFill.Add(availableFeature);
}
}
}
would I run into problems with this? Since could they not pass in an array(that has a fixed size)? Would it be better maybe for a concrete List?
There are three questions here: what type should I use for a formal parameter? What should I use for a local variable? and what should I use for a return type?
Formal parameters:
The principle here is do not ask for more than you need. IEnumerable<T> communicates "I need to get the elements of this sequence from beginning to end". IList<T> communicates "I need to get and set the elements of this sequence in arbitrary order". List<T> communicates "I need to get and set the elements of this sequence in arbitrary order and I only accept lists; I do not accept arrays."
By asking for more than you need, you (1) make the caller do unnecessary work to satisfy your unnecessary demands, and (2) communicate falsehoods to the reader. Ask only for what you're going to use. That way if the caller has a sequence, they don't need to call ToList on it to satisfy your demand.
Local variables:
Use whatever you want. It's your method. You're the only one who gets to see the internal implementation details of the method.
Return type:
Same principle as before, reversed. Offer the bare minimum that your caller requires. If the caller only requires the ability to enumerate the sequence, only give them an IEnumerable<T>.
The most practical reason I've ever seen was given by Jeffrey Richter in CLR via C#.
The pattern is to take the basest class or interface possible for your arguments and return the most specific class or interface possible for your return types. This gives your callers the most flexibility in passing in types to your methods and the most opportunities to cast/reuse the return values.
For example, the following method
public void PrintTypes(IEnumerable items)
{
foreach(var item in items)
Console.WriteLine(item.GetType().FullName);
}
allows the method to be called passing in any type that can be cast to an enumerable. If you were more specific
public void PrintTypes(List items)
then, say, if you had an array and wished to print their type names to the console, you would first have to create a new List and fill it with your types. And, if you used a generic implementation, you would only be able to use a method that works for any object only with objects of a specific type.
When talking about return types, the more specific you are, the more flexible callers can be with it.
public List<string> GetNames()
you can use this return type to iterate the names
foreach(var name in GetNames())
or you can index directly into the collection
Console.WriteLine(GetNames()[0])
Whereas, if you were getting back a less specific type
public IEnumerable GetNames()
you would have to massage the return type to get the first value
Console.WriteLine(GetNames().OfType<string>().First());
IEnumerable<T> allows you to iterate through a collection. ICollection<T> builds on this and also allows for adding and removing items. IList<T> also allows for accessing and modifying them at a specific index. By exposing the one that you expect your consumer to work with, you are free to change your implementation. List<T> happens to implement all three of those interfaces.
If you expose your property as a List<T> or even an IList<T> when all you want your consumer to have is the ability to iterate through the collection. Then they could come to depend on the fact that they can modify the list. Then later if you decide to convert the actual data store from a List<T> to a Dictionary<T,U> and expose the dictionary keys as the actual value for the property (I have had to do exactly this before). Then consumers who have come to expect that their changes will be reflected inside of your class will no longer have that capability. That's a big problem! If you expose the List<T> as an IEnumerable<T> you can comfortably predict that your collection is not being modified externally. That is one of the powers of exposing List<T> as any of the above interfaces.
This level of abstraction goes the other direction when it belongs to method parameters. When you pass your list to a method that accepts IEnumerable<T> you can be sure that your list is not going to be modified. When you are the person implementing the method and you say you accept an IEnumerable<T> because all you need to do is iterate through that list. Then the person calling the method is free to call it with any data type that is enumerable. This allows your code to be used in unexpected, but perfectly valid ways.
From this it follows that your method implementation can represent its local variables however you wish. The implementation details are not exposed. Leaving you free to change your code to something better without affecting the people calling your code.
You cannot predict the future. Assuming that a property's type will always be beneficial as a List<T> is immediately limiting your ability to adapt to unforeseen expectations of your code. Yes, you may never change that data type from a List<T> but you can be sure that if you have to. Your code is ready for it.
Short Answer:
You pass the interface so that no matter what concrete implementation of that interface you use, your code will support it.
If you use a concrete implementation of list, another implementation of the same list will not be supported by your code.
Read a bit on inheritance and polymorphism.
Here's an example: I had a project once where our lists got very large, and resulting fragmentation of the large object heap was hurting performance. We replaced List with LinkedList. LinkedList does not contain an array, so all of a sudden, we had almost no use of the large object heap.
Mostly, we used the lists as IEnumerable<T>, anyway, so there was no further change needed. (And yes, I would recommend declaring references as IEnumerable if all you're doing is enumerating them.) In a couple of places, we needed the list indexer, so we wrote an inefficient IList<T> wrapper around the linked lists. We needed the list indexer infrequently, so the inefficiency was not a problem. If it had been, we could have provided some other implementation of IList, perhaps as a collection of small-enough arrays, that would have been more efficiently indexable while also avoiding large objects.
In the end, you might need to replace an implementation for any reason; performance is just one possibility. Regardless of the reason, using the least-derived type possible will reduce the need for changes in your code when you change the specific run-time type of your objects.
Inside the method, you should use var, instead of IList or List. When your data source changes to come from a method instead, your onlySomeInts method will survive.
The reason to use IList instead of List as parameters, is because many things implement IList (List and [], as two examples), but only one thing implements List. It's more flexible to code to the interface.
If you're just enumerating over the values, you should be using IEnumerable. Every type of datatype that can hold more than one value implements IEnumerable (or should) and makes your method hugely flexible.
Using IList instead of List makes writing unit tests significantly easier. It allows you to use a 'Mocking' library to pass and return data.
The other general reason for using interfaces is to expose the minimum amount of knowledge necessary to the user of an object.
Consider the (contrived) case where I have a data object that implements IList.
public class MyDataObject : IList<int>
{
public void Method1()
{
...
}
// etc
}
Your functions above only care about being able to iterate over a list. Ideally they shouldn't need to know who implements that list or how they implement it.
In your example, IEnumerable is a better choice as you thought.
It is always a good idea to reduce the dependencies between your code as much as possible.
Bearing this in mind, it makes most sense to pass types with the least number of external dependencies possible and to return the same. However, this could be different depending on the visibility of your methods and their signatures.
If your methods form part of an interface, the methods will need to be defined using types available to that interface. Concrete types will probably not be available to interfaces, so they would have to return non-concrete types. You would want to do this if you were creating a framework, for example.
However, if you are not writing a framework, it may be advantageous to pass parameter with the weakest possible types (i.e. base classes, interfaces, or even delegates) and return concrete types. That gives the caller the ability to do as much as possible with the returned object, even if it is cast as an interface. However, this makes the method more fragile, as any change to the returned object type may break the calling code. In practice though, that generally isn't a major problem.
You accept an Interface as a parameter for a method because that allows the caller to submit different concrete types as arguments. Given your example method LogAllChecked, the parameter someClasses could be of various types, and for the person writing the method, all might be equivalent (i.e. you'd write the exact same code regardless of the type of the parameter). But for the person calling the method, it can make a huge difference -- if they have an array and you're asking for a list, they have to change the array to a list or v.v. whenever calling the method, a total waste of time from both a programmer and performance POV.
Whether you return an Interface or a concrete type depends upon what you want to let your callers do with the object you created -- this is an API design decision, and there's no hard and fast rule. You have to weigh their ability to make full use of the object against their ability to easily use a portion of the objects functionality (and of course whether you WANT them to be making full use of the object). For instance, if you return an IEnumerable, then you are limiting them to iterating -- they can't add or remove items from your object, they can only act against the objects. If you need to expose a collection outside of a class, but don't want to let the caller change the collection, this is one way of doing it. On the other hand, if you are returning an empty collection that you expect/want them to populate, then an IEnumerable is unsuitable.
Here's my answer in this .NET 4.5+ world.
Use IList<T> and IReadonlyList<T>,
instead of List<T>, because ReadonlyList<T> doesn't exist.
IList<T> looks so consistent with IReadonlyList<T>
Use IEnumerable<T> for minimum exposure (property) or requirement (parameter) if foreach is the only way to use it.
Use IReadonlyList<T> if you also need to expose/use Count and [] indexer.
Use IList<T> if you also allow callers to add/update/delete elements
because List<T> implements IReadonlyList<T>, it doesn't need any explicit casting.
An example class:
// manipulate the list within the class
private List<int> _numbers;
// callers can add/update/remove elements, but cannot reassign a new list to this property
public IList<int> Numbers { get { return _numbers; } }
// callers can use: .Count and .ReadonlyNumbers[idx], but cannot add/update/remove elements
public IReadOnlyList<int> ReadonlyNumbers { get { return _numbers; } }