Casting List<MyObject> to IEnumerable<MyInterface> - c#

I'm still learning some of this c# stuff, and I couldn't find an answer to this question. Assuming that I have a list of MyObject implementing MyInterface
public class MyObject : IMyInterface { ...}
public List<MyObject> MyObjectList;
How can I return an IEnumerable<IMyInterface> with the contents of MyObjectList?
I mean, right now I have this:
List<IMyInterface> temp = new List<IMyInterface>();
foreach (MyObject obj in MyObjects) temp.Add(obj);
return (IEnumerable<IMyInterface>)temp;
But is it necessary to create a new list like this?
Thank you.

If you're using .NET 3.5, the easiest way to do this is:
return MyObjects.Cast<IMyInterface>();
You don't need to create a copy of everything - but until C# 4 comes out with its generic interface variance, you're stuck doing something like this.
If you're still using .NET 2.0, you can easily do something similar:
public static IEnumerable<TResult> SafeCast<TSource, TResult>
(IEnumerable<TSource> source) where TResult : TSource
{
foreach (TSource item in source)
{
yield return item;
}
}
(Note that this doesn't check for source being null; to do that properly you'd want two methods due to the deferred execution of iterator blocks.)
Then use:
return SafeCast<MyObject, IMyInterface>(MyObjects);
You could make it more like the LINQ version, like this:
public static IEnumerable<T> SafeCast<T>(IEnumerable source)
{
foreach (T item in source)
{
yield return item;
}
}
return SafeCast<IMyInterface>(MyObjects);
This has compile-time safety though - it wouldn't stop you from trying to convert a List<string> into an IEnumerable<Guid> for example.

Using the LINQ Cast method works well here, something like MyObjects.Cast()

If you're using C# 3 and .NET 3.5 (or above), then you can use the LINQ suggestion that Jake presented:
return MyObjectList.Cast<IMyInterface>();
(There's no need for AsEnumerable in this particular circumstance)
However, if you're using a prior version (2.0 of C# and .NET or above), you can still use an iterator block:
foreach(MyObject obj in MyObjectList) yield return (IMyInterface)obj;

Related

Return same Type as Generic Class

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;
}

Simple way to implement a Collection?

I am developing a collection class, which should implement IEnumerator and IEnumerable.
In my first approach, I implemented them directly. Now I have discovered the yield keyword, and I have been able to simplify everything a whole lot substituting the IEnumerator/IEnumerable interfaces with a readonly property Values that uses yield to return an IEnumerable in a loop.
My question: is it possible to use yield in such a way that I could iterate over the class itself, without implementing IEnumerable/IEnumerator?
I.e., I want to have a functionality similar to the framework collections:
List<int> myList = new List<int>();
foreach (int i in myList)
{
...
}
Is this possible at all?
Update: It seems that my question was badly worded. I don't mind implementing IEnumerator or IEnumerable; I just thought the only way to do it was with the old Current/MoveNext/Reset methods.
You won't have to implement IEnumerable<T> or IEnumerable to get foreach to work - but it would be a good idea to do so. It's very easy to do:
public class Foo : IEnumerable<Bar>
{
public IEnumerator<Bar> GetEnumerator()
{
// Use yield return here, or
// just return Values.GetEnumerator()
}
// Explicit interface implementation for non-generic
// interface; delegates to generic implementation.
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
The alternative which doesn't implement IEnumerable<T> would just call your Values property, but still providing a GetEnumerator() method:
public class Foo
{
public IEnumerator<Bar> GetEnumerator()
{
// Use yield return here, or
// just return Values.GetEnumerator()
}
]
While this will work, it means you won't be able to pass your collection to anything expecting an IEnumerable<T>, such as LINQ to Objects.
It's a little-known fact that foreach will work with any type supporting a GetEnumerator() method which returns a type with appropriate MoveNext() and Current members. This was really to allow strongly-typed collections before generics, where iterating over the collection wouldn't box value types etc. There's really no call for it now, IMO.
You could do somthing like this, but why? IEnumerator is already simple.
Interface MyEnumerator<T>
{
public T GetNext();
}
public static class MyEnumeratorExtender
{
public static void MyForeach<T>(this MyEnumerator<T> enumerator,
Action<T> action)
{
T item = enumerator.GetNext();
while (item != null)
{
action.Invoke(item);
item = enumerator.GetNext();
}
}
}
I'd rather have the in keyword and I wouldn't want to rewrite linq.

T in class? AddRange ICollection?

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.

Best way to convert IList or IEnumerable to Array

I have a HQL query that can generate either an IList of results, or an IEnumerable of results.
However, I want it to return an array of the Entity that I'm selecting, what would be the best way of accomplishing that? I can either enumerate through it and build the array, or use CopyTo() a defined array.
Is there any better way? I went with the CopyTo-approach.
Which version of .NET are you using? If it's .NET 3.5, I'd just call ToArray() and be done with it.
If you only have a non-generic IEnumerable, do something like this:
IEnumerable query = ...;
MyEntityType[] array = query.Cast<MyEntityType>().ToArray();
If you don't know the type within that method but the method's callers do know it, make the method generic and try this:
public static void T[] PerformQuery<T>()
{
IEnumerable query = ...;
T[] array = query.Cast<T>().ToArray();
return array;
}
Put the following in your .cs file:
using System.Linq;
You will then be able to use the following extension method from System.Linq.Enumerable:
public static TSource[] ToArray<TSource>(this System.Collections.Generic.IEnumerable<TSource> source)
I.e.
IEnumerable<object> query = ...;
object[] bob = query.ToArray();
I feel like reinventing the wheel...
public static T[] ConvertToArray<T>(this IEnumerable<T> enumerable)
{
if (enumerable == null)
throw new ArgumentNullException("enumerable");
return enumerable as T[] ?? enumerable.ToArray();
}
In case you don't have Linq, I solved it the following way:
private T[] GetArray<T>(IList<T> iList) where T: new()
{
var result = new T[iList.Count];
iList.CopyTo(result, 0);
return result;
}
Hope it helps

Does dot net have an interface like IEnumerable with a Count property?

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);
}
}
}

Categories