开发者

Understanding Generics combined with inherited classes

This is a question related to another one I asked that was specific to NHibernate, but I'm starting to think that my question might be far more fundamental than that.

ForNHibernate-related reasons, I have a base abstract class (Listing) and classes that inherit from it (Listing_UK, Listing_US, etc).

These are functionally identical.

I understand why this does not work:

List<Listing> test = new List<Listing_UK>();

Right now I'm doing the equivalent of this:

List<Listing> test = new List<开发者_开发百科;Listing>();
test.Add(new Listing_UK() as Listing);

which works, but I need the classes to be more interchangeable, like the above.

I appreciate that the fundamental idea behind what I'm doing is a little weird, but does anyone have any advice?

EDIT:

I've clearly made my examples way too abstract.

I was trying to avoid making this too NHibernate-specific so that it's actually different from my other question (and because I think what I'm asking is more fundamental), but what I basically want to achieve is this:

IQueryOver<Listing,Listing> test = null;
if(condition) {
  test = DBSession.QueryOver<Listing_UK>();
} else {
  test = DBSession.QueryOver<Listing_US>();
}
test.Where(l => l.Field == "value").List<Listing>();

From the reactions I am getting here, I'm reasonably sure that what I'm asking for is not possible.


There's no need to use "as" in the code you've got. This will work fine:

List<Listing> test = new List<Listing>();
test.Add(new Listing_UK());

It's not really clear what you need to do which you can't do already. Do you actually need a List<Listing_UK>? What's the bigger picture here? If you could show some code which doesn't work, that would help.

EDIT: Okay, now that you've explained a bit more, I suspect you want a generic method:

List<Listing> list = condition ? QueryList<Listing_UK>() 
                               : QueryList<Listing_US>();

private static List<Listing> QueryList<T>() where T : Listing
{
    return DBSession.QueryOver<T>()
                    .Where(l => l.Field == "value")
                    .List<Listing>();
}

I don't know NHibernate well enough to know whether that's enough already, but if not I'm sure you could adjust it slightly.

Your original thought of just trying to treat the types interchangably really isn't going to work.


If Listing_UK inherits from the abstract class Listing, you don't need to do any casting when you add it to your List. Downcasts like that are implicit.

List<Listing> test = new List<Listing>();
test.Add(new Listing_UK());

Then when you want to deal with each Listing, you'll just have to deal with their types at that point.

foreach (Listing listing in test)
{
    listing.Update();
    if (listing is Listing_UK)
        ((Listing_UK)listing).PunchTheQueen();
}

Simple!


class Foo : Bar { }

void Test(List<Bar> list);

Remember that you can do:

List<Bar> list = new List<Bar>();
Test (list);

but you can't:

List<Foo> list = new List<Foo>();
Test (list);

to achieve that, use:

void Test2 <T> (List<T> list) where T : Bar    

or

List<Foo> list = new List<Foo>();
Test (list.Cast<Bar>().ToList()); // not ToList<Bar>()

That's because

Bar is Bar; // true
Foo is Bar; // true
List<Foo> is List<Foo>; // true
List<Bar> is List<Bar>; // true

but

List<Foo> is List<Bar>; // false!
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜