0

I am trying to customize List. I have it mostly figured out but am coming across a problem. Here is the code I am working with:

public class MyT
{
    public int ID { get; set; }
    public MyT Set(string Line)
    {
        int x = 0;

        this.ID = Convert.ToInt32(Line);

        return this;
    }
}

public class MyList<T> : List<T> where T : MyT, new()
{
    internal T Add(T n)
    {
        Read();
        Add(n);
        return n;
    }
    internal MyList<T> Read()
    {
        Clear();
        StreamReader sr = new StreamReader(@"../../Files/" + GetType().Name + ".txt");
        while (!sr.EndOfStream)
            Add(new T().Set(sr.ReadLine())); //<----Here is my error!
        sr.Close();
        return this;
    }
}

public class Customer : MyT
{
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Item : MyT
{
    public int ID { get; set; }
    public string Category { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
}

public class MyClass
{
    MyList<Customer> Customers = new MyList<Customer>();
    MyList<Item> Items = new MyList<Item>();
}

In the code, you can see that I am trying to create a customize List. Here you also see two of the many classes that I have. All of the classes have an ID. All of the classes are matched with a custom List. The problem seems to be in MyList<T>.Read() - Add(new T().Set(sr.ReadLine())); Lastly, I get that MyT can not be converted to T. I need to know how to fix it.

Axarydax
  • 16,353
  • 21
  • 92
  • 151
Makai
  • 567
  • 3
  • 9
  • 18
  • An extension method would probably be better unless subclassing really matters to you. – user703016 May 10 '13 at 09:51
  • 5
    `where T : MyT` if T can only be `MyT`, why do you use Generics? – I4V May 10 '13 at 09:52
  • 1
    I4V: It uses the generic version that compiles to MyT instead of the non-generic that only uses objects inside, which can be slower due to casting; and there can be subclasses of MyT... – Luis Filipe May 10 '13 at 10:00
  • 3
    Extending `List<>` like this feels awful wrong. Better have a completely different class that creates the list from file. – Dialecticus May 10 '13 at 10:01
  • 1
    What functionality are you adding to the List class? In my experience, extending the List class is rarely the way to go. Instead, if type A needs to maintain a collection of type B, use a regular List and add some methods to type A to perform specific operations on the List. – Rik May 10 '13 at 10:02
  • Also, you're doing something strange with your MyT inheritance relationship; MyT has an ID property, but so do the classes that inherit from it, hiding the ID property in MyT. – Rik May 10 '13 at 10:03
  • 2
    @Makai: I'd consider on encapsulating a List<> in my own class instead of inheriting from it; – Luis Filipe May 10 '13 at 10:03
  • That code is really confusing. Your `Add` method calls `Read`, and `Read` calls `Add` in a loop. It's difficult to say if this is going to lead to an infinite loop, or if one of those calls to `Add` resolves to `base.Add` (doesn't look like it). In any case, you shouldn't be extending `List` in this way. Have your `MyT` class declare a factory method that can read a file and create the list. – Jim Mischel May 10 '13 at 21:37
  • As far as your first comment, I have a very long list of objects that need to go into a List and all of the Lists need to do some set things that I could add to each and every list individually without any problems, but it is a very long list and I would have to do it to each and every one. That is a tedious ordeal especially if I decide later to make a change. That is why I am trying to make a custom list that applies the same properties to all objects that it lists out. I have most of it working properly except this one thing. I just don't know how to fix it – Makai May 10 '13 at 23:01

1 Answers1

1

The Set method returns the type MyT instead of the specific type. Make it generic so that it can return the specific type:

public T Set<T>(string Line) where T : MyT {
    int x = 0;
    this.ID = Convert.ToInt32(Line);
    return (T)this;
}

Usage:

Add(new T().Set<T>(sr.ReadLine()));

Or cast the reference back to the specific type:

Add((T)(new T().Set(sr.ReadLine())));
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • I tried what you recommended. The first usage you gave still gives exactly the same error as before. The second gives a new error. _Error 6: The type arguments for method 'MyT.Set(string)' cannot be inferred from the usage. Try specifying the type arguments explicitly." I don't know what this means._ – Makai May 10 '13 at 19:08
  • @Makai: Sorry, the method should of course have the return type `T`, not `MyT`. When you get that error from the second code, it means that you modified the method as in the first example, and try to use it as in the second example. – Guffa May 10 '13 at 21:06