Casting a generic typed object per subtype

I have the following script in my code:

class Document
{}

class Track : Document
{}

class ViewListClickHandler
{
    // I can't change that signature, it provided by a library I use.
    protected override void click(object theList, int index)
    {
        // I here need to cast "theList" to IList<T> where T : Document
    }
}

      

Now my question (as written in the comment):

How can I apply this theList

to a type type IList<T> where T : Document

?

The difficulty in this case is that I can get any class by extending Document

in this list. And this is the same for me what I get. I just want to pass it to a list containing some documents.

EDIT:

Sorry forgot to mention this. theList

sometimes is an object compatible with IList<Document>

, sometimes IList<Track>

or generally typed by another subtype Document

.

I need to do this in one layer. I have another example where it is not an IList but another typically typed class where I cannot loop.

+3


source to share


5 answers


You can use OfType :



var documents = theList.OfType<Document>();

      

+4


source


The problem here is covariance and contravariance. For casting subtypes, you need to have a common covariant interface. IEnumerable and IQueryable are good examples of this. The only thing you need is that each method of this interface returns objects of type T (covariance) or if the interface methods only receive an object of type T (contravariance) and the in / out word is required to define the interface. EX:

// covariance
public interface ICovarianct<out T>{
    IEnumerable<T> Get();
}

// contravariance
public interface Contravariant<in T>{
    void Method(T arg)
}

      

Then, in your specific example, you cannot use casting because IList is not a covariate. You can use LINQ extensions like:



OfType<T>() //to enumerate only the items of certain types.

all.OfType<Document>() 

      

will return all documents in the collection

Hope for this help!

+2


source


Just call (IList<Document>) theList

or if the elements do not Documents

make the 2-step path: first discard object theList

before IList<object>

. Then we iterate over each element and check if it is Document

.

+1


source


You can't cast an open generic type - why not just cast it to IList<Document>

? It's not entirely clear, but you seem to be saying that you will only call the method with a list of documents?

0


source


//Provided that theList was either List<Track> or List<Document> or any class derived from Document. You can just cast using this statement

List<Document> documents = theList as List<Document>;

      

-1


source







All Articles