I try to do static class, add to icollection but i got some issues i cant seem to overcome. that is how i get so i can pass a ICollection in the method? cause T is that say it can not be resolved.
and then i wonder is there a way to do AddRange on icollection?
i was thinking of something like this but maby i am way out of my mind with it?
public static ICollection<T> add(this IEnumerable<T> list)
{
ICollection<T> collection = null;
return collection.AddRange(list);
}
No, ICollection<T> doesn't have an AddRange method - and even if it did, you'd be trying to dereference null which will throw a NullReferenceException. You haven't specified a collection to add the list to... what exactly are you trying to do?
You could create (say) a new List<T> - and that has the benefit of already having a constructor which can take an IEnumerable<T>:
public static ICollection<T> Add<T>(this IEnumerable<T> list)
{
return new List<T>(list);
}
However, at that point you've really just reimplemented Enumerable.ToList() and given it a different return type...
If you want to add everything to an existing collection, you might want something like this:
public static ICollection<T> AddTo<T>(this IEnumerable<T> list,
ICollection<T> collection)
{
foreach (T item in list)
{
collection.Add(item);
}
return collection;
}
If I understand correctly you want to add a IEnumerable<T> to an empty collection.
Wouldn't it be easier to just do:
ICollection<MyObject> collection = new List<MyObject>(GetIEnumerableOfMyObject());
Or even:
ICollection<MyObject> collection = GetIEnumerableOfMyObject().ToList();
The other ways seem to assume that your ICollection is empty and/or your ICollection is a type of List. However, if you want AddRange, then you can Extend the ICollection class as follows:
public static void AddRange<T>(this ICollection<T> ic, IEnumerable<T> ie)
{
foreach (T obj in ie)
{
ic.Add(obj);
}
}
Note, however, that since List impliments ICollection, this may cause ambiguity when dealing directly with List objects (though I haven't tested yet if the compiler will be able to resolve it--my gut reaction is that it should, though, since AddRange is a member of List and the compiler will go through member functions first before looking at extensions, but if I'm wrong I'm sure someone will correct me).
Depending on the collection type of your source list an alternative approach is to use List(T).ForEach, as in:
List<string> source = ...
ICollection<string> dest = ...
source.Foreach(dest.Add);
However, the readability of this is easy to dispute.
Related
Wasn't really sure how to phrase the title.
What I am trying to achieve is a deep clone system for IEnumerable<T>s where T:ICloneable.
I have written the, as-yet untested, method below which I believe should work:
public static IEnumerable<T> DeepClone<T>(this IEnumerable<T> source) where T:ICloneable
{
return source.Select(s => (T) s.Clone());
}
However, this returns an IEnumerable<T> (as one would expect) and I am curious as to whether or not it is possible (without causing an unacceptable overhead) to return the base type of the IEnumerable<T> instead.
For example, running List<int>.DeepClone() would return a new, cloned List<int> and running int[].DeepClone() would return a new, cloned int[].
I know that I can quite easily just cast my IEnumerables after calling this method, but I'm hoping to be able to avoid this.
There is also the option of creating a whole load of overloads, one for each IEnumerable but if it's possible to I'd like to avoid this.
You will need to build explicit methods for the concrete types you want to support (List, arrays etc).
An example:
public static List<T> DeepClone<T>(this List<T> source) where T : ICloneable
{
return source.Select(s => (T)s.Clone()).ToList();
}
Alternatively, use an approach like:
public static IEnumerable<T> DeepClone<T>(this IEnumerable<T> source) where T : ICloneable
{
var result = source.Select(s => (T)s.Clone());
if (source is List<T>)
{
return result.ToList();
}
return result;
}
I have user defined type Items which inherits IList, ICollection, IEnumerable. How to convert this type to HashSet<Items>. I am using below snippet, is there any efficient way to this?
public static class Extensions
{
public static bool AddRange<T>(this HashSet<T> #this, IEnumerable<T> items)
{
bool allAdded = true;
foreach (T item in items)
{
added &= #this.Add(item);
}
return allAdded;
}
}
A HashSet<T> has a constructor which accepts an IEnumerable<T> and instantiates that HashSet from the collection. You could simply call that.
If you want to load the items in your custom type into an existing HashSet, you'd probably want to use the HashSet's UnionWith method, which:
Modifies the current HashSet object to contain all elements that are present in itself, the specified collection, or both.
What these two options won't do, however, is give you a result specifying if any items didn't make it through the conversion. You'd be able to do it later, though, by calling one of HashSet's other methods, such as IsSupersetOf, or simply comparing Counts.
I have a question similar to this one, but pertaining to EntityCollection<>.
EntityCollection implements Remove(), allowing you to remove a single item from the list at once. However, I'd like to implement an extension method that can remove multiple items at once, similar to IList<T>'s RemoveAll(Predicate<T> match) method.
One idea would be to loop through the list, and remove items. Something like:
public static void RemoveAll<T>(this EntityCollection<T> collection, Predicate<T> match) where T : EntityObject
{
foreach (T o in collection)
{
if (match(o))
collection.Remove(o);
}
}
However, this will throw an exception because you can't modify the collection you're iterating through.
Another idea would be to build a temporary list of items to remove, then loop through that list and remove each item from the collection. However, this seems inefficient to me. Is there a better implementation?
As I said in comments, iterating over a secondary list is probably the only safe choice here.
You can implement it with something like:
public static void RemoveAll<T>(this EntityCollection<T> collection,
Predicate<T> match) where T : EntityObject
{
if (match == null) {
throw new ArgumentNullException("match");
}
collection.Where(entity => match(entity))
.ToList().ForEach(entity => collection.Remove(entity));
}
I have a custom List MyList that is an extension of List, and I have an IEnumerable (or IQueryable) which I want to do .ToList() on, but I guess, .ToMyList().
How can I implement the ToList() method? The source code for ToList() is to create a new List() and pass in the IEnumerable as a parameter, but I am not sure what it does with it.
If your class subclasses List<T>, and you provide the correct constructor, you should be able to do:
MyList<MyType> list = new MyList<MyType>(theEnumerable);
If you want a simple extension method, similar to Enumerable.ToList, you could write your own:
public static MyList<T> ToMyList<T>(this IEnumerable<T> theEnumerable)
{
return new MyList<T>(theEnumerable);
}
You could then call this via:
var list = theEnumerable.ToMyList();
Note that subclassing List<T>, in general, is really not a very good idea. You should really consider subclassing Collection<T> and implementing IList<T>, if you need a custom collection, instead. You can still provide the same constructors and use the methods above to populate the custom collection, if required.
If you have a base class and you are able to delegate list population to its constructor, do that:
public MyList(IEnumerable<MyType> items) : base(items) { }
Otherwise, this constructor should work for almost any collection class:
public MyList(IEnumerable<MyType> items)
{
if (items == null)
throw new ArgumentNullException("items");
foreach (var item in items)
Add(item);
}
Then you can write an extension method, or call this constructor directly to populate a new list from a sequence.
Does dot net have an interface like IEnumerable with a count property? I know about interfaces such as IList and ICollection which do offer a Count property but it seems like these interfaces were designed for mutable data structures first and use as a read only interface seems like an afterthought - the presence of an IsReadOnly field and mutators throwing exceptions when this property is true is IMO ample evidence for this.
For the time being I am using a custom interface called IReadOnlyCollection (see my own answer to this post) but I would be glad to know of other alternative approaches.
The key difference between the ICollection family and the IEnumerable family is the absence of certainty as to the count of items present (quite often the items will be generated/loaded/hydrated as needed) - in some cases, an Enumerable may not ever finish generating results, which is why the Count is missing.
Deriving and adding a Count is possible depending on your requirements, but it goes against this spirit, which is the purpose of ICollection - a collection of stuff that's all there.
Another way might be to use the System.Linq.Enumerable.Count method, i.e.
using System.Linq;
class X
{
void Y(IEnumerable<int> collection)
{
int itemCount = collection.Count();
}
}
or use the (System.Linq.Enumerable) .ToList() to pull all the items from the enumerator into a Collection and work from there.
(Also to answer your comment before having 50 rep:- the ".Count()" bit is a call to an extension method on the extension class System.Linq.Enumerable - the extension method is available on all things that derive from IEnumerable because the code has a "using System.Linq" which brings the extension methods in all classes in that namespace into scope - in this case its in the class Enumerable. If you're in VS, pressing F12 will bring you to the definition of S.L.Enumerable. BTW C# In Depth is a fantastic book for learning LINQ properly - its a page turner thats really helps you get the whole picture compared to learning the bits of LINQ piece by piece)
As of .Net 4.5, there are two new interfaces for this: IReadOnlyCollection<T> and IReadOnlyList<T>.
IReadOnlyCollection<T> is IEnumerable<T> with a Count property added, IReadOnlyList<T> also adds indexing.
It sounds like you really just want ReadOnlyCollection<T> - expose it as IList<T>, but by wrapping the original list like this you just get a read-only wrapper with an appropriate count.
Taking into consideration some of the comments I have decided to go with a wrapper class implementing a custom interface...
interface IReadOnlyCollection<T> : IEnumerable<T>
{
int Count { get; }
}
//This can now be not misused by downcasting to List
//The wrapper can also be used with lists since IList inherits from ICollection
public class CollectionWrapper<T> : IReadOnlyCollection<T>
{
public CollectionWrapper(ICollection<T> collection)
{
_collection = collection;
}
public int Count
{
get
{
return _collection.Count;
}
}
public IEnumerator<T> GetEnumerator()
{
return (IEnumerator<T>)_collection.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)((IEnumerable)_collection).GetEnumerator();
}
////////Private data///////
ICollection<T> _collection;
}
class Program
{
static void Main(string[] args)
{
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
CollectionWrapper<int> collection = new CollectionWrapper<int>(list);
Console.WriteLine("Count:{0}", collection.Count);
foreach (var x in collection)
{
Console.WriteLine(x);
}
foreach (var x in (IEnumerable)collection)
{
Console.WriteLine(x);
}
}
}
Thanks all for your suggestions.
Edit: Now cannot be misused by downcasting to List (or whatever).
IList can return IsReadOnly as true, which marks the collection as readonly. Other than that I'm afraid I don't know of anything fitting.
Since it's an interface, you would have to implement the Count property yourself, why don't you create a new interface that inherits IEnumerator and add a Count property?
IList or ICollection would be the way to go, if you want to use the standard interfaces.
Note that you can "hide" methods required by the interface if you don't want them in your class's public interface -- for example, since it's meaningless to add things to a readonly collection you can do this:
void ICollection<DataType>.Add(DataType item)
{
throw new NotSupportedException();
}
public DataType this[int index]
{
get { return InnerList[index]; }
}
DataType IList<DataType>.this[int index]
{
get { return this[index]; }
set { throw new NotSupportedException(); }
}
etc.
An array can be cast to an IList, which makes the IList ReadOnly == true :)
You can get .Count on IEnumerable with an extension method if you add a reference to System.Linq (in 3.5 anyway).
As Jon Skeet mentions, you're much better off using System.Collections.ObjectModel.ReadOnlyCollection instead of creating your own wrapper class.
Then you can implement your sample as follows:
class Program {
static void Main(string[] args) {
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
ReadOnlyCollection<int> collection = new ReadOnlyCollection<int>(list);
Console.WriteLine("Count:{0}", collection.Count);
foreach (var x in collection) {
Console.WriteLine(x);
}
foreach (var x in (IEnumerable)collection) {
Console.WriteLine(x);
}
}
}