Simple existing implementation of ICollection<T> - c#

Is there a simple implementation of ICollection<T> in .NET framework? I.e. a collection class with ability to add and remove items, but without indexing. Collection<T> definitely does not fit, as it implements IList as well and so elements can be accessed by index.
Exposing Collection<T> or List<T> as ICollection<T> will not work in my case too, because I need to inherit my own class from it, and a class inherited from any other class that implements IList<T> will have indexing as well.
I know it is not a big deal to implement one myself, but just thought it should already exist, searched for but did not found anything similar.

Here's a list of classes that implement ICollection<T> in the System.Collections namespace:
System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>
System.Collections.Generic.Dictionary<TKey, TValue>
System.Collections.Generic.HashSet<T>
System.Collections.Generic.LinkedList<T>
System.Collections.Generic.List<T>
System.Collections.Generic.SortedDictionary<TKey, TValue>
System.Collections.Generic.SortedList<TKey, TValue>
System.Collections.Generic.SortedSet<T>
System.Collections.ObjectModel.Collection<T>
System.Collections.ObjectModel.ReadOnlyCollection<T>
System.Collections.ObjectModel.ReadOnlyDictionary<TKey, TValue>
System.Collections.ObjectModel.WeakReadOnlyCollection<T>
But all of those implementations add extra functionality, and since you want to inherit from an implementation, but only expose ICollection<T> methods, using any of them is not really an option.
The only choice you have is to implement your own. It's easy enough to do. You just need to wrap a suitable implementation of ICollection<T>. Here's one that uses a List<T> by default, but also allows derived classes to use a specific type of ICollection<T>:
class SimpleCollection<T> : ICollection<T>
{
ICollection<T> _items;
public SimpleCollection() {
// Default to using a List<T>.
_items = new List<T>();
}
protected SimpleCollection(ICollection<T> collection) {
// Let derived classes specify the exact type of ICollection<T> to wrap.
_items = collection;
}
public void Add(T item) {
_items.Add(item);
}
public void Clear() {
_items.Clear();
}
public bool Contains(T item) {
return _items.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex) {
_items.CopyTo(array, arrayIndex);
}
public int Count
{
get { return _items.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
return _items.Remove(item);
}
public IEnumerator<T> GetEnumerator()
{
return _items.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _items.GetEnumerator();
}
}
This is going beyond what you're after, but if, for example, you wanted unique items to be stored, you could derive from this and provide a HashSet<T> as the collection type to wrap:
class UniqueCollection<T> : SimpleCollection<T>
{
public UniqueCollection() : base(new HashSet<T>()) {}
}

Hashset<T>
should work if you would like it to be unordered with unique values.
See MSDN
As mentioned in the comments, ICollection<T> is an even simpler collection that is unordered and will allow duplicate entries. MSDN
ICollection<string> unordered = new Collection<string>();
Finally, I am not aware of a "simple" native .NET implementation of a collection that has .Add() / .Remove() functionality without exposing an index. So, to answer your question, it looks like for your niche functionality you'll have to roll your own.

Just to give a quick differences:
SortedList
Is the best way to use to by get keys rather index and it is based on binary search. Internally, it uses two lists: IList and IList. It does not use Dictionary. Thus it does not have any Hash values.
SortedDictionary is same as SortedList. However, the difference is internal development. Sorted Dictionary is using B Tree. Thus modifications are fast, and lookups are same as sorted list.
Difference between HashSet and List is HashSet ensures uniqueness. That means if you try to add the value twice, it will ignore that value without giving any error or duplicating the same.
So if you don't want to use index based then you can use SortedList that is inherited from ICollection and then IEnumerable...
Otherwise HashSet is the best option where uniqueness is important.

Related

C# - How to create fixed size SortedList?

I only found that SortedList contains IsFixedSize property but I can't find answer to that simple question anywhere.
This property is something inherited from IDictionary, since SortedList implements it. This property will always return false for the default implementation of SortedList (as stated in the msdn documentation), simply because the default implementation is not fixed size.
Fixed size means that the collection disallows any Add or Remove type operations (anything that would change the underlying collection, not only the contained elements) after it's constructed via a wrapper (again, the docs). So if you want a SortedList of fixed size, you should create your own wrapper, something like
public class SortedListFixed<TKey, TValue> : SortedList<TKey, TValue>
{
private SortedList<TKey, TValue> _list;
public bool IsFixedSize => true;
/** ctors **/
public void Add(TKey key, TValue value) =>
throw InvalidOperationException("This collection is fixed size");
public bool Remove (TKey key) =>
throw InvalidOperationException("This collection is fixed size");
/** etc. for all inherited size-modifying methods **/
}
Two ctors would come in handy, one that takes a capacity, creates the underlying _list with that capacity, and a wrapping ctor taking an existing SortedList as a parameter. You could also combine the latter with a neat extension method like this:
public static class SortedListExtensions
{
public static SortedListFixed<TKey, TValue> ToFixedSize<TKey, TValue>(
this SortedList<TKey, TValue> list) => new SortedListFixed<TKey, TValue>(list);
}
Note that it's more a guideline than a whole implementation.

Some clarifications about IEnumerable interface in C#?

I am pretty new in C# (I came from Java) and I have a doubt about the use of:
I have this class:
namespace DataModel.MaliciousCode
{
public class PagedMalicious : Shared.Paged
{
public IEnumerable<MaliciousSmall> MaliciousCode { get; set; }
}
}
As you can see this class contains only a IEnumerable<MaliciousSmall> MaliciousCode
Reading the online documentation it seems to me to understand that IEnumerable is an interface that give me an iterator on a non generic collection.
What exactly means the previous assertion?
I have MaliciousSmall that is the type of a model object in my application (an object that contains some properties that map the fields of a table on the DB)
So my doubt are:
IEnumerable<MaliciousSmall> MaliciousCode: MaliciousCode is an iterable collection of MaliciousSmall objects? So it means that it represent a collection and some provided methods to iterate on it?
If the previous assertion is true, ok MaliciousCode object is an iterable collection but IEnumerable is an interface so who implement the method to iterate on this collection (coming from Java I think that an interface is not provided of implemented methods)
Some one can help me to understand these things?
Tnx
Andrea
IEnumerable<MaliciousSmall> MaliciousCode: MaliciousCode is an iterable collection of MaliciousSmall objects? So it means that it represent a collection and some provided methods to iterate on it?
Sort of - IEnumerable<T> provides one method - GetEnumerator - which returns an IEnumerator<T>. THAT interface allows you to iterate over the collection. Pre-Linq all IEnumerable allowed you to do was use the collection in a foreach loop (or use the provided IEnumerator directly, which is rare). Linq has since defined extension methods on IEumerable<T> that allow more sophisticated queries like Select, Where, Count, etc.
If the previous assertion is true, ok MaliciousCode object is an iterable collection but IEnumerable is an interface so who implement the method to iterate on this collection (coming from Java I think that an interface is not provided of implemented methods)
Typically the implementation is provided by using an underlying collection type like List<MaliciousSmall> or MaliciousSmall[]. So the IEnumerable implementation is provided by that class. The yield keyword introduced in C# 2.0 allows you to "return" an IEnumerable<T> and let the compiler provide the actual implementation.
So in your class, you might internally implement the collection as a List<T>:
public class PagedMalicious : Shared.Paged
{
public IEnumerable<MaliciousSmall> MaliciousCode { get; set; }
public PagedMalicious()
{
MaliciousCode = new List<MaliciousSmall>();
}
// other private methods that add to MaliciousCode
}
The use of IEnumerable<T> allows you to change the internal implementation without changing the public interface.
Your property MaliciousCode, represents an object of a class that implements IEnumerable<T> interface. On it's own, IEnumerable does not really mean anything. It just provides a structure. It is user's responsibility to implement the methods that are provided with interface whatever way the see it suitable.
Edit: Here is a simple example to demonstrate:
private void Form3_Load(object sender, EventArgs e)
{
Parent parent = new Parent();
parent.Child = new List<Child>(); // -> this is where implementer is decided.
//Before this line, Child property is not instantiated and is not referring to any object.
}
public class Parent
{
public IEnumerable<Child> Child { get; set; }
}
public class Child
{
public int MyProperty { get; set; }
}
To your doubts:
Yes and Yes
The interface itself can't implement anything, but you can assign an array of MaliciousSmall or a List<MaliciousSmall>. Both of them implement IEnumerable<MaliciousSmall>
IEnumerable<T> is the equivalent of Java's Iterable<T>. Since the early versions of C# did not have generics, IEnumerable was the only iterator available at that time. You can think of it as a kind of IEnumerable<object>.
Most generic collection types implement IEnumerable<T>, including arrays. The generic variant requires the non-generic variant to be implemented, therefore most collections (generic or not) implement IEnumerable.
However, these iterators are not limited to represent collections. They provide methods that allow you to enumerate items and these methods can generate items algorithmically as well. For instance an - in theory - endless enumeration of square numbers could be provided by an enumeration without the requirement to store those numbers anywhere.
In your case the IEnumerable<MaliciousSmall> MaliciousCode property could yield MaliciousSmall objects from the DB one by one as the enumeration is being enumerated without storing them in a collection object first.
Implementing IEnumerable<T> yourself requires the implementation of the IEnumerator<T> GetEnumerator() method. It returns an enumerator object which requires the implementation of the methods bool MoveNext(), void Dispose(), void Reset() and the property T Current { get; }.
You can implement these interfaces the good old way, by writing a lot of code, or you can use C#'s iterators. Iterators use a lot of compiler magic to create enumerables and enumerators automatically behind the scenes. See: Iterators (C# and Visual Basic).
As an example of C# iterators, let's implement your example with them (I dropped the setter as it stands in the way here):
public class PagedMalicious : Shared.Paged
{
public IEnumerable<MaliciousSmall> MaliciousCode
{
get
{
using (var conn = new SqlConnection("<my server connection>")) {
var cmd = new SqlCommand("SELECT name, number FROM myTable", conn);
conn.Open();
using (var reader = cmd.ExecuteReader()) {
while (reader.Read()) {
var maliciousSmall = new MaliciousSmall {
Name = reader.GetString(0),
Number = reader.GetInt32(1)
};
yield return maliciousSmall;
}
}
}
}
}
}
Each time yield return is executed, the control is passed back to the caller and he gets the next item. The state of the getter method is kept intact and its execution is halted here until the caller continues iterating and requires the next item. When he does so, the execution resumes just after the yield return statement.
You can see from this example, that enumerations are evaluated in a lazy way. The following code sums up the numbers of the whole table. The items are never stored in a collection; they are retrieved from the DB and created as they are enumerated. This is an advantage, if you have one million records! (You would use an SQL SUM aggregate function in a productive piece of code, so.)
var pagedMalicious = new PagedMalicious();
int sum = 0;
foreach (MaliciousSmall item in pagedMalicious.MaliciousCode) {
sum += item.Number;
}

IEnumerable constructor overload

I have some custom list which is based on IEnumerable<T>. Now I want to overload the constructor and do some custom stuff with the initial list I get.
//Constructor
public CustomList(IEnumerable<T> collection) : base(collection)
{
//do some stuff with the collection e.g. iterate
foreach(T obj in collection)
{
//do some stuff with obj
}
}
Is it even possible to do so? Because IEnumerable can only be enumerated once at base(collection), but the loop will fail, I guess.
EDIT:
since it is not completely clear for everyone: My base class is IEnumerable<T> and IEnumerable can only be enumerated once in my case.
Assuming your base class is List<T>, then the base constructor adds all the items to the current object. So you could do the following as often as you want:
foreach (T obj in this) { }
But I've heard it's a bad idea to inherit from List<T>, that you should implement IList<T> instead, even if it is just a wrapper around List<T>. I just can't remember why that is.

IList<T> and IReadOnlyList<T>

If I have a method that requires a parameter that,
Has a Count property
Has an integer indexer (get-only)
What should the type of this parameter be? I would choose IList<T> before .NET 4.5 since there was no other indexable collection interface for this and arrays implement it, which is a big plus.
But .NET 4.5 introduces the new IReadOnlyList<T> interface and I want my method to support that, too. How can I write this method to support both IList<T> and IReadOnlyList<T> without violating the basic principles like DRY?
Edit: Daniel's answer gave me some ideas:
public void Foo<T>(IList<T> list)
=> Foo(list, list.Count, (c, i) => c[i]);
public void Foo<T>(IReadOnlyList<T> list)
=> Foo(list, list.Count, (c, i) => c[i]);
private void Foo<TList, TItem>(
TList list, int count, Func<TList, int, TItem> indexer)
where TList : IEnumerable<TItem>
{
// Stuff
}
Edit 2: Or I could just accept an IReadOnlyList<T> and provide a helper like this:
public static class CollectionEx
{
public static IReadOnlyList<T> AsReadOnly<T>(this IList<T> list)
{
if (list == null)
throw new ArgumentNullException(nameof(list));
return list as IReadOnlyList<T> ?? new ReadOnlyWrapper<T>(list);
}
private sealed class ReadOnlyWrapper<T> : IReadOnlyList<T>
{
private readonly IList<T> _list;
public ReadOnlyWrapper(IList<T> list) => _list = list;
public int Count => _list.Count;
public T this[int index] => _list[index];
public IEnumerator<T> GetEnumerator() => _list.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
Then I could call it like Foo(list.AsReadOnly())
Edit 3: Arrays implement both IList<T> and IReadOnlyList<T>, so does the List<T> class. This makes it pretty rare to find a class that implements IList<T> but not IReadOnlyList<T>.
You are out of luck here. IList<T> doesn't implement IReadOnlyList<T>. List<T> does implement both interfaces, but I think that's not what you want.
However, you can use LINQ:
The Count() extension method internally checks whether the instance in fact is a collection and then uses the Count property.
The ElementAt() extension method internally checks whether the instance in fact is a list and than uses the indexer.
Since IList<T> and IReadOnlyList<T> do not share any useful "ancestor", and if you don't want your method to accept any other type of parameter, the only thing you can do is provide two overloads.
If you decide that reusing codes is a top priority then you could have these overloads forward the call to a private method that accepts IEnumerable<T> and uses LINQ in the manner Daniel suggests, in effect letting LINQ do the normalization at runtime.
However IMHO it would probably be better to just copy/paste the code once and just keep two independent overloads that differ on just the type of argument; I don't believe that micro-architecture of this scale offers anything tangible, and on the other hand it requires non-obvious maneuvers and is slower.
If you're more concerned with maintaining the principal of DRY over performance, you could use dynamic, like so:
public void Do<T>(IList<T> collection)
{
DoInternal(collection, collection.Count, i => collection[i]);
}
public void Do<T>(IReadOnlyList<T> collection)
{
DoInternal(collection, collection.Count, i => collection[i]);
}
private void DoInternal(dynamic collection, int count, Func<int, T> indexer)
{
// Get the count.
int count = collection.Count;
}
However, I can't say in good faith that I'd recommend this as the pitfalls are too great:
Every call on collection in DoInternal will be resolved at run time. You lose type safety, compile-time checks, etc.
Performance degradation (while not severe, for the singular case, but can be when aggregated) will occur
Your helper suggestion is the most useful, but I think you should flip it around; given that the IReadOnlyList<T> interface was introduced in .NET 4.5, many API's don't have support for it, but have support for the IList<T> interface.
That said, you should create an AsList wrapper, which takes an IReadOnlyList<T> and returns a wrapper in an IList<T> implementation.
However, if you want to emphasize on your API that you are taking an IReadOnlyList<T> (to emphasize the fact that you aren't mutating the data), then the AsReadOnlyList extension that you have now would be more appropriate, but I'd make the following optimization to AsReadOnly:
public static IReadOnlyList<T> AsReadOnly<T>(this IList<T> collection)
{
if (collection == null)
throw new ArgumentNullException("collection");
// Type-sniff, no need to create a wrapper when collection
// is an IReadOnlyList<T> *already*.
IReadOnlyList<T> list = collection as IReadOnlyList<T>;
// If not null, return that.
if (list != null) return list;
// Wrap.
return new ReadOnlyWrapper<T>(collection);
}
What you need is the IReadOnlyCollection<T> available in .Net 4.5 which is essentially an IEnumerable<T> which has Count as the property but if you need indexing as well then you need IReadOnlyList<T> which would also give an indexer.
I don't know about you but I think this interface is a must have that had been missing for a very long time.

.NET: How to check the type within a generic typed class?

How do I get the type of a generic typed class within the class?
An example:
I build a generic typed collection implementing ICollection< T>. Within I have methods like
public void Add(T item){
...
}
public void Add(IEnumerable<T> enumItems){
...
}
How can I ask within the method for the given type T?
The reason for my question is: If object is used as T the collection uses Add(object item) instead of Add(IEnumerable<object> enumItems) even if the parameter is IEnumerable. So in the first case it would add the whole enumerable collection as one object instead of multiple objects of the enumerable collection.
So i need something like
if (T is object) {
// Check for IEnumerable
}
but of course that cannot work in C#. Suggestions?
Thank you very much!
Michael
You can use: typeof(T)
if (typeof(T) == typeof(object) ) {
// Check for IEnumerable
}
Personally, I would side step the issue by renaming the IEnumerable<T> method to AddRange. This avoids such issues, and is consistent with existing APIs such as List<T>.AddRange.
It also keeps things clean when the T you want to add implements IEnumerable<T> (rare, I'll admit).
If you want to use the is operator in a generic class/method you have to limit T to a reference type:
public void MyMethod<T>(T theItem) where T : class
{
if (theItem is IEnumerable) { DoStuff(); }
}

Categories

Resources