简体   繁体   中英

How do i convert a List<Interface> to List<Class> in c#

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.

使用LINQ:

Ireaders.Cast<ReaderInfo>().ToList();

通过使用Linq

var derivedList = Ireaders.Cast<ReaderInfo>();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM