I am new to enumerating collections so forgive if this question sounds silly.
I have an class
public class PersonStuff : IPersonStuff, IEnumerable<User>
{
Person person = new Person();
...
IEnumerator<Person> IEnumerable<Person>.GetEnumerator()
{
return (person as IEnumerable<Person>).GetEnumerator();
}
}
As you can see, I am implementing two interfaces in the above: one being IPersonStuff and the other being IEnumerable.
The Person class is a simple getter/setter each type being of string e.g. name, address except dateofbirth which is DateTime.
And in my IPersonStuff I have this:
interface IPersonStuff
{
...
IEnumerator<Person> IEnumerable<Person>.GetEnumerator();
}
Once working, I would like to call it in the following manner (from any class):
IPersonStuff personStuff = new PersonStuff();
foreach (Person u in personStuff)
{
//this loop should iterate thru the elements.
}
However, I get the following error:
'IEnumerable<...>.GetEnumerator': explicit interface declaration can only be declared in a class or struct
Basically I want to know how is it possible to call the IEnumerator IEnumerable.GetEnumerator() I have in the PersonStuff class through the IPersonStuff Interface.
Is IPersonStuff itself collection-like, or just a bunch of properties? If it's not collection-like, there's no need to make it enumerable.
I believe the error is due to using System.Collections.Generic but not System.Collections -- the non-generic IEnumerable is thus not in scope.
I think that if you want IPersonStuff to be enumerable then you can just have IPersonStuff inherit IEnumerable<T> (which in turn inherits IEnumerable). Otherwise, I don't think you'll be able to use foreach over a reference to IPersonStuff.
EDIT Based on further comments and edits, it looks like PersonStuff is intended to be a collection-like data access class for Person, with instantiation managed in monostate fashion.
The monostate instantiation defeats the point of defining an interface IPersonStuff: if you always create it with new PersonStuff() in-line, then (bar bytecode postprocessing) there is no opportunity to use some non-default implementation of the interface.
I would suggest defining some sort of data access context object with properties representing each of your global entity collections, then pass that around in your choice of fashion -- using a parameter or accessor-based singleton is preferable to a monostate. This object may then wrap a database connection, NHibernate session, or similar.
You're getting the error most probably because like what Jeffrey said you're missing a reference to System.Collections.Generic which has the non-generic IEnumerable. Once you have the correct reference you won't need the cast of (person as IEnumerable).
On whether it should/can be type safe depends on your situation. If all elements of what you're enumerating through are of the same type (i.e. fixed class, interface or subclass) that you should/can use the type safe IEnumerable. But if say maybe you want to enumerate all the properties in Person (which sounds like what you might be attempting) and you're returning diff types then you'll have to use the non-generic IEnumerable.
If you are enumerating through the properties of your class then one nice trick is to use yield return for each property (instead of writing a custom class that implements IEnumerator) in Person.GetEnumerator();
Related
I am trying to play with Reflection and ran into the following situation.
In the following code, let's assume that the 'obj' can be of types IEnumerable<> or ICollection<> or IList<>.
I would like to cast this System.Object to IEnumerable<> always (as ICollection<> and IList<> inherit from IEnumerable<> anyway), so that i would like to enumerate over the collection and use reflection to write the individual items.
Motivation behind this is I am just trying to see if how would Serializers, in general, serialize data and so I am trying to simulate that situation in the hope to understand Reflection too.
I thought of casting the object to non-generic IEnumerable, but thought that this would cause unnecessary boxing of objects, when let's say the actual instance of IEnumerable<int>...am I thinking right?
private void WriteGenericCollection(object obj)
{
Type innerType = obj.GetType().GetGenericArguments()[0];
//Example: IEnumerable<int> or IEnumerable<Customer>
Type generatedType = typeof(IEnumerable<>).MakeGenericType(innerType);
//how could i enumerate over the individual items?
}
Well, since you don't know the actual type of the items until runtime, you don't need to use the generic IEnumerable<T> interface; just use the non-generic one, IEnumerable (the generic one inherits from it):
private void WriteGenericCollection(object obj)
{
IEnumerable enumerable = (IEnumerable)obj;
foreach(object item in enumerable)
{
...
}
}
Your question is rife with misconceptions. Let's clear them up.
In the following code, let's assume that the 'obj' can be of types
IEnumerable<> or ICollection<> or IList<>.
If that is true, and if you know the type of enumerable, a better way of writing the method would be
private void WriteGenericCollection<T>(IEnumerable<T> obj)
{
// ...
}
I would like to downcast this System.Object to IEnumerable<> always
(as ICollection<> and IList<> inherit from IEnumerable<> anyway), so
that i would like to enumerate over the collection and use reflection
to write the individual items.
"Inherit" is not a correct term when talking about interfaces; it could also give you the wrong ideas. Interfaces are best thought of as contracts: when considering to implement an interface, you can only decide to implement it as the author intended or not implement it at all.
Some interfaces are supersets of other interfaces; their contracts say "implementors must do this in addition to whatever else that contract says". But there is never any sharing of implementation as is common in inheritance, because interfaces do not have any.
"Downcasting" is also not the correct term for what you are doing in that method. Downcasting means casting to a more derived class; there's also casting to an interface:
// Note: the method is still generic!
private void WriteGenericCollection<T>(object obj)
{
var casted = (IEnumerable<T>)obj;
}
I thought of downcasting the object to non-generic IEnumerable, but
thought that this would cause unnecessary boxing of objects, when
let's say the actual instance of IEnumerable...am I thinking right?
Boxing would occur if and only if the object was an IEnumerable<T> where T is a value type (a numeric type, a bool, an enum or a struct). If the object implements IEnumerable<T> for some known T then you can simply cast it to that. If T is unknown then cast to non-generic IEnumerable and take the possible performance hit (there is no way around it in any case).
You would only need to use reflection if you know nothing about the object (in which case of course you also need to have a plan for objects that cannot be enumerated, otherwise why allow passing them to your method in the first place?).
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.
If I have two classes:
public class A { }
public class B : A { }
and I create a generic container and a function that takes it:
public void Foo(List<A> lst) { ... }
I get an invalid conversion if I attempt casting a List<B> to a List<A>, and instead have to pass it like so:
var derivedList = new List<B>();
Foo(new List<A>(derivedList));
Is there some way to pass a List<B> to this function without the overhead of allocating a brand new list, or does C# not support converting from a generic container of a derived type to its base type?
A List<B> simply isn't a List<A> - after all, you can add a plain A to a List<A>, but not to a List<B>.
If you're using C# 4 and .NET 4 and your Foo method only really needs to iterate over the list, then change the method to:
public void Foo(IEnumerable<A> lst) { ... }
In .NET 4, IEnumerable<T> is covariant in T, which allows a conversion from IEnumerable<B> (including a List<B>) to IEnumerable<A>. This is safe because values only ever flow "out" of IEnumerable<A>.
For a much more detailed look at this, you can watch the video of the session I gave at NDC 2010 as part of the torrent of NDC 2010 videos.
This is not possible. C# doesn't support co / contra variance on concrete types such as List<T>. It does support it on interfaces though so if you switch Foo to the following signature you can avoid an allocation
public void Foo(IEnumerable<A> enumerable) { ...
If you wish to pass list-like things to routines which are going to read them but not write them, it would be possible to define a generic covariant IReadableList<out T> interface, so that an IReadableList<Cat> could be passed to a routine expecting an IReadableList<Animal>. Unfortunately, common existing IList<T> implementations don't implement any such thing, and so the only way to implement one would be to implement a wrapper class (which could accept an IList as a parameter), but it probably wouldn't be too hard. Such a class should also implement non-generic IList, also as read-only, to allow code to evaluate Count without having to know the type of the items in the list.
Note that an object's implementation of IReadableList<T> should not be regarded as any promise of immutability. It would be perfectly reasonable to have a read-write list or wrapper class implement IReadableList<T>, since a read-write list is readable. It's not possible to use an IReadableList<T> to modify a list without casting it to something else, but there's no guarantee a list passed as IReadableList<T> can't be modified some other way, such as by casting it to something else, or by using a reference stored elsewhere.
I have a function like this:
DoSomething(List<IMyInterface>)
IMyInterface is an interface and MyClass is a class implementing this interface
Class MyClass:IMyInterface
I call DoSomething(List<MyClass>) and it looks it doesn't work.
How could I pass the list of a class to a list of the interface of the class as function's parameter? Thanks!
If your code is simply iterating over the sequence inside the method (not adding, removing, or accessing by index), change your method to one of the following
DoSomething(IEnumerable<IMyInterface> sequence)
DoSomething<T>(IEnumerable<T> sequence) where T : IMyInterface
The IEnumerable<> interface is covariant (as of .NET 4) (first option). Or you could use the latter signature if using C# 3.
Otherwise, if you need indexed operations, convert the list prior to passing it. In the invocation, you might have
// invocation using existing method signature
DoSomething(yourList.Cast<IMyInterface>().ToList());
// or updating method signature to make it generic
DoSomething<T>(IList<T> list) where T : IMyInterface
What the latter signature would allow you to do is to also support adds or removes to the list (visible at the callsite), and it would also let you use the list without first copying it.
Even still, if all you do is iterate over the list in a loop, I would favor a method acceping IEnumerable<>.
This is not safe in general because Lists are mutable. Suppose you pass someone a reference to a List<MyClass> as a List<IMyInterface>, then they do:
void Foo(List<IMyInterface> list)
{
IMyInterface x = new MyOtherClassWhichAlsoImplementsIMyInterface();
list.Add(x);
}
Now your List<MyClass> contains an instance of a class that is not a MyClass. This would violate type safety. (As other answers noted, you can avoid this problem by passing only the IEnumerable<> interface of List, which provides read-only access and so is safe).
For more details, see Using Variance in Interfaces for Generic Collections on MSDN. See also a good summary of covariance and contravariance and various C# features that support it.
If you only need to go through the list, declare the method with an IEnumerable. If you want to add elements to the list, what you're asking isn't typesafe and might not be allowed in C# as a result.
I know that IList is the interface and List is the concrete type but I still don't know when to use each one. What I'm doing now is if I don't need the Sort or FindAll methods I use the interface. Am I right? Is there a better way to decide when to use the interface or the concrete type?
There are two rules I follow:
Accept the most basic type that will work
Return the richest type your user will need
So when writing a function or method that takes a collection, write it not to take a List, but an IList<T>, an ICollection<T>, or IEnumerable<T>. The generic interfaces will still work even for heterogenous lists because System.Object can be a T too. Doing this will save you headache if you decide to use a Stack or some other data structure further down the road. If all you need to do in the function is foreach through it, IEnumerable<T> is really all you should be asking for.
On the other hand, when returning an object out of a function, you want to give the user the richest possible set of operations without them having to cast around. So in that case, if it's a List<T> internally, return a copy as a List<T>.
Microsoft guidelines as checked by FxCop discourage use of List<T> in public APIs - prefer IList<T>.
Incidentally, I now almost always declare one-dimensional arrays as IList<T>, which means I can consistently use the IList<T>.Count property rather than Array.Length. For example:
public interface IMyApi
{
IList<int> GetReadOnlyValues();
}
public class MyApiImplementation : IMyApi
{
public IList<int> GetReadOnlyValues()
{
List<int> myList = new List<int>();
... populate list
return myList.AsReadOnly();
}
}
public class MyMockApiImplementationForUnitTests : IMyApi
{
public IList<int> GetReadOnlyValues()
{
IList<int> testValues = new int[] { 1, 2, 3 };
return testValues;
}
}
IEnumerable
You should try and use the least specific type that suits your purpose.
IEnumerable is less specific than IList.
You use IEnumerable when you want to loop through the items in a collection.
IList
IList implements IEnumerable.
You should use IList when you need access by index to your collection, add and delete elements, etc...
List
List implements IList.
There's an important thing that people always seem to overlook:
You can pass a plain array to something which accepts an IList<T> parameter, and then you can call IList.Add() and will receive a runtime exception:
Unhandled Exception: System.NotSupportedException: Collection was of a fixed size.
For example, consider the following code:
private void test(IList<int> list)
{
list.Add(1);
}
If you call that as follows, you will get a runtime exception:
int[] array = new int[0];
test(array);
This happens because using plain arrays with IList<T> violates the Liskov substitution principle.
For this reason, if you are calling IList<T>.Add() you may want to consider requiring a List<T> instead of an IList<T>.
I would agree with Lee's advice for taking parameters, but not returning.
If you specify your methods to return an interface that means you are free to change the exact implementation later on without the consuming method ever knowing. I thought I'd never need to change from a List<T> but had to later change to use a custom list library for the extra functionality it provided. Because I'd only returned an IList<T> none of the people that used the library had to change their code.
Of course that only need apply to methods that are externally visible (i.e. public methods). I personally use interfaces even in internal code, but as you are able to change all the code yourself if you make breaking changes it's not strictly necessary.
It's always best to use the lowest base type possible. This gives the implementer of your interface, or consumer of your method, the opportunity to use whatever they like behind the scenes.
For collections you should aim to use IEnumerable where possible. This gives the most flexibility but is not always suited.
If you're working within a single method (or even in a single class or assembly in some cases) and no one outside is going to see what you're doing, use the fullness of a List. But if you're interacting with outside code, like when you're returning a list from a method, then you only want to declare the interface without necessarily tying yourself to a specific implementation, especially if you have no control over who compiles against your code afterward. If you started with a concrete type and you decided to change to another one, even if it uses the same interface, you're going to break someone else's code unless you started off with an interface or abstract base type.
You are most often better of using the most general usable type, in this case the IList or even better the IEnumerable interface, so that you can switch the implementation conveniently at a later time.
However, in .NET 2.0, there is an annoying thing - IList does not have a Sort() method. You can use a supplied adapter instead:
ArrayList.Adapter(list).Sort()
I don't think there are hard and fast rules for this type of thing, but I usually go by the guideline of using the lightest possible way until absolutely necessary.
For example, let's say you have a Person class and a Group class. A Group instance has many people, so a List here would make sense. When I declare the list object in Group I will use an IList<Person> and instantiate it as a List.
public class Group {
private IList<Person> people;
public Group() {
this.people = new List<Person>();
}
}
And, if you don't even need everything in IList you can always use IEnumerable too. With modern compilers and processors, I don't think there is really any speed difference, so this is more just a matter of style.
You should use the interface only if you need it, e.g., if your list is casted to an IList implementation other than List. This is true when, for example, you use NHibernate, which casts ILists into an NHibernate bag object when retrieving data.
If List is the only implementation that you will ever use for a certain collection, feel free to declare it as a concrete List implementation.
In situations I usually come across, I rarely use IList directly.
Usually I just use it as an argument to a method
void ProcessArrayData(IList almostAnyTypeOfArray)
{
// Do some stuff with the IList array
}
This will allow me to do generic processing on almost any array in the .NET framework, unless it uses IEnumerable and not IList, which happens sometimes.
It really comes down to the kind of functionality you need. I'd suggest using the List class in most cases. IList is best for when you need to make a custom array that could have some very specific rules that you'd like to encapsulate within a collection so you don't repeat yourself, but still want .NET to recognize it as a list.
A List object allows you to create a list, add things to it, remove it, update it, index into it and etc. List is used whenever you just want a generic list where you specify object type in it and that's it.
IList on the other hand is an Interface. Basically, if you want to create your own custom List, say a list class called BookList, then you can use the Interface to give you basic methods and structure to your new class. IList is for when you want to create your own, special sub-class that implements List.
Another difference is:
IList is an Interface and cannot be instantiated. List is a class and can be instantiated. It means:
IList<string> list1 = new IList<string>(); // this is wrong, and won't compile
IList<string> list2 = new List<string>(); // this will compile
List<string> list3 = new List<string>(); // this will compile