1

I have a class that subclass a generic List. I did it to implement a toJSONString() that I need to call regularly on this kind of list. So my class is something like this:

public class Foos : List<Foo>
{
    public string toJSONString()
    {
        //Do something here
    }
}

In another Class i have a method doing this:

public class Bar
{
    private Foos m_Foos = new m_Foos();

    public Foos filterWith(Query p_query)
    {
        Foos newList = m_Foos.FindAll(
            // Make a test through a delegate
        });

        return (newList);
    }
}

I get this error:

Error CS0266: Cannot implicitly convert type System.Collections.Generic.List<Foo>' toFoos'. An explicit conversion exists (are you missing a cast?) (CS0266) (Assembly-CSharp)

The problem is that m_Foos.FindAll(...) return a "List" not a "Foos". Explicit casting doesn't do the trick, because I then have a runtime error.

I have read this post, but it doesn't seem to give an appropriate solution to my problem: C# - Why can I not cast a List<MyObject> to a class that inherits from List<MyObject>?

Community
  • 1
  • 1
matt
  • 1,046
  • 1
  • 13
  • 26
  • Would adding a couple of extension methods to the List class be an acceptable solution for you? [Here's an example](http://stackoverflow.com/questions/6632392/extension-method-for-listt-addtofrontt-object-how-to) – Scampbell Jul 14 '14 at 12:54
  • Why exactly do you need to inherit from `List` in order to implement `toJSONString`? Wouldn't `JSONUtilities.toString(m_Foos)` work? – Jon Jul 14 '14 at 12:56

3 Answers3

5

Do not write a new class just to add such formatting method. Use extension method instead on your list:

public static class FooListExtensions
{
    public static string toJSONString(this List<Foo> list)
    {
        return "...";
    }
}

Then you can simply:

List<Foo> list = new List<Foo>();
var str = list.toJSONString();
Konrad Kokosa
  • 16,563
  • 2
  • 36
  • 58
  • 1
    Thanx guys, @Konrad: Your solution works like a charm. I didn't knew the extensions system (I have a C++ background). Very elegant solution – matt Jul 14 '14 at 13:08
0
m_Foos.FindAll(
            // Make a test through a delegate
});

This method returns List<Foo>. You cannot cast List<Foo> to Foos, (only Foos -> List<Foo> - due to inheritance).

You could prepare sufficient constructor:

public class Foos : List<Foo>
{
    public Foos() 
    {
    }

    public Foos(List<Foo> otherList) 
       : base(otherList)
    {
    }

    public string toJSONString()
    {
        //Do something here
    }
}

Then:

Foos newList = new Foos(m_Foos.FindAll(/* delegate */));
0

This has to do with Liskov Substitution Principle. Let's say you have classes Rectangle and Square and that square inherits from a rectangle. You can cast square to a rectangle - square is a rectangle with 4 same sides, but you cannot cast rectangle into a square since rectangle is not a square. In other words you can cast up the inheritance tree but not down the inheritance tree.

I would follow Konrad's suggestion and make it into an extension method if the only reason why you created a Foos class is so that you can convert it to a JSON...

Marko
  • 12,543
  • 10
  • 48
  • 58
  • Thanx for your answer Marko. Indeed I thought it was possible to explicit-cast a class into a subclass, in the case of that subclass just added some new methods (no new members). But it is definitly not possible. So I did it as Konrad said, with extensions, and it's working very well. Thanx again – matt Jul 14 '14 at 13:10