I have an interface defined as
public interface IReaderInfo
{
string Displayname {get;}
}
and a class that implements that interface
public class ReaderInfo : IReaderInfo
{
string DisplayName {get;}
}
I then created a function which return List
public List<ReaderInfo> GetReaders
{
var readers = new List<ReaderInfo>();
var Ireaders = someobject.Getreaders();// Returns the list of IReaderInfo.
// Now i would like cast Ireaders as readers and return.
}
How do i cast it?
You have to create a new list with casted items:
var readers = Ireaders.Cast<ReaderInfo>().ToList();
Or, if there is a possibility to have incompatible IReaderInfo entries and you only want the actual ReaderInfo objects in the result:
var readers = Ireaders.OfType<ReaderInfo>().ToList();
The quick&very-dirty fix is to pass only the objects that actually are ReaderInfo, by using OfType<>. Using Cast<> will fail if any of the objects implements IReaderInfo
without actually being a ReaderInfo
var Ireaders = someobject.Getreaders();
var readers=Ireaders.OfType<ReaderInfo>().ToList();
return readers;
A better solution though would be to change the method's signature to return a List<IReaderInfo>
, or the more abstract IList<IReaderInfo>
. If GetReaders
returns a list of interfaces it means it can return any object that implements the interface.
Why discard some of them? Why should GetReaders
decide which objects to use and which to discard when all implement the same interface?
public IList<IReaderInfo> GetReaders
{
var readers = new List<ReaderInfo>();
var Ireaders = someobject.Getreaders();// Returns the list of IReaderInfo.
return Ireaders;
}
For example, methods typically return interfaces when they do intend to return different types, eg mock objects, or handle multiple implementations. By returning List<ReaderInfo>
you prevent your method from handling valid objects
UPDATE
Versioning is another very strong reason why one shouldn't cast interfaces to concrete types.
Googling for IReaderInfo I found a couple of pages that refer to RFID readers. A ReaderInfo returns the capabilities of a reader, but how do you expose new features for a new reader?
A common way to expose new features without breaking compatibility is to introduce a new class that implement the old interface IReaderInfo
and place expose new features through a new interface, eg IReaderInfo2
. Or the existing class can be extended with IReaderInfo2
. A library can do that because clients are expected to work only through the interfaces, not directly against the concrete classes.
Using LINQ:
Ireaders.Cast<ReaderInfo>().ToList();
By using Linq
var derivedList = Ireaders.Cast<ReaderInfo>();