How do i convert a List to List

2020-03-26 04:46发布

问题:

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?

回答1:

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


回答2:

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.



回答3:

Using LINQ:

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


回答4:

By using Linq

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


标签: c# oop casting