VIRA
VIRA

Reputation: 1504

Generic type's causing issue C#.net

I have class called GroupItem, i can store any type here say int, string, decimal, datetime etc.., Then, i have GroupItems which will store any groupItem. I'm using an arraylist to store all the groupItem.

public class GroupItem<T>
{
    private string heading;
    private List<T> items = new List<T>();

    public GroupItem() { }

    public string Heading
    {
        get { return heading; }
        set { heading = value; }
    }

    public List<T> Items
    {
        get { return items; }
        set { items = value; }
    }

    public void Add(T value)
    {
        this.items.Add(value);
    }

    public T this[int index]
    {
        get
        {
            return this.items[index];
        }
    }
}

public class GroupItems
{
    private string groupName;
    private List<object> items = new List<object>();

    public string GroupName
    {
        get { return groupName; }
        set { groupName = value; }
    }

    public GroupItems() { }

    public void Add(object value)
    {
        this.items.Add(value);
    }

    public object this[int index]
    {
        get
        {
            return this.items[index];
        }
    }
}

I want to retrieve from GroupItems. How i can get generic item's values in groupItems?

I'm now inserting two items, datetime and int to groupitems. Now i want to retrieve groupitems[2] value but how i can convert this to groupItem without knowing what it is. Even we may get its genericarguments by getType().getGenericarguments()[0]. But how i can create an instance based upon that.

Upvotes: 1

Views: 139

Answers (7)

VIRA
VIRA

Reputation: 1504

Thanks for your inputs.

I have resolved it myself using multiple overloading methods to resolve this.

for example:

private void Print(GroupItem<string> items)
{
///custom coding
}
private void Print(GroupItem<int> items)
{
///custom coding
}

Though its not efficient enough, i want to do in this way as it was .net 2.0.

I'm now improving this in .Net 4.0 with new algorithm.

Thanks a lot for all of your helps.

Upvotes: 0

phoog
phoog

Reputation: 43056

Consider: you have a collection of items; the items may have any runtime type (string, int, etc.). Because of this, the static type of the collections items must be object.

It seems that you want to be able to retrieve items from the list with strong static typing. That's not possible without a lot of conditional logic (or reflection). For example:

object item = collection[0];
if (item is int)
    //do something with an int
else if (item is string)
    //do something with a string

Now suppose instead of "doing something" with the value of collection[0], we assign the value to a variable. We can do one of two things:

  • use the same variable for both cases, in which case the static type must be object.
  • use separate variables, in which case the static type will be string or int, but outside of the conditional logic, we can't know which variable holds the value of collection[0].

Neither option really solves the problem.

By creating GroupItem<T>, you add a level of indirection to this problem, but the underlying problem is still there. As an exercise, try reworking the example, but starting from "Consider: you have a collection of items; the items are of type GroupItem<T> where T may be any runtime type (string, int, etc.)."

Upvotes: 0

Samuel Slade
Samuel Slade

Reputation: 8623

There are two situations that could be covered by your question:

  1. You want to simply store a collection of GroupItem's of type T in the class GroupItems.
  2. You want to store a collection of generic GroupItem's of any type in the class GroupItems. To better clarify, I mean that you could store GroupItem<DateTime> or GroupItem<int> in the same GroupItems class.

Here are some ways of going about storing and retrieving for both scenarios:

Same Type

public class GroupItem<T>
{
    // ... Code for GroupItem<T>
}

public class GroupItems<T>
{
    private List<GroupItem<T>> mItems = new List<GroupItem<T>>();

    public void Add(T item)
    {
        mItems.Add(item);
    }

    public T GetItem(int index)
    {
        return mItems[index];
    }
}

Here you will build a collections that contain GroupItem's of the same time, so a collection of GroupItem<DateTime> for example. All the items will be of the same type.

Generic Type

public interface IGroupItem
{
    // ... Common GroupItem properties and methods
}

public class GroupItem<T>
{
    // ... Code for GroupItem<T>
}

public class GroupItems
{
    private List<IGroupItem> mItems = new List<IGroupItem>();

    public void Add(IGroupItem item)
    {
        mItems.Add(item);
    }

    // This is a generic method to retrieve just any group item.
    public IGroupItem GetItem(int index)
    {
        return mItems[index];
    }

    // This is a method that will get a group item at the specified index
    // and then cast it to the specific group item type container.
    public GroupItem<T> GetItem<T>(int index)
    {
        return (GroupItem<T>)mItems[index];
    }
}

Here you will be able to build and maintain a single collection that can contain any GroupItem with any Type. So you could have a GroupItems collection that contains items of GroupItem<DateTime>, GroupItem<int>, etc.

Please note that none of these code examples take into account any erroneous circumstances.

Upvotes: 0

Arnon Rotem-Gal-Oz
Arnon Rotem-Gal-Oz

Reputation: 25929

Depending on what you do with GroupItem you should either inherit from List/Collection as was offered by other or use a generic collection inside your class e.g.

    class GroupItem<T> 
{
    private List<T> items = new List<T>();

    public void Add(T value)
    {
        items.Add(value);


    }
    public T Get()
    {
       //replace with some logic to detemine what to get
       return items.First();

    }

}

Upvotes: 0

Marc Gravell
Marc Gravell

Reputation: 1064084

If the list is storing heterogeneous items, then I would suggest you need a common non-generic interface or base-class. So, say we have

interface IGroupItem {
// the non-generic members, and maybe
// "object Value {get;}" etc, and maybe
// "Type ItemTypr {get;}"
}

You would then have:

class GroupItem<T> : IGroupItem {...}

an you would then use

List<IGroupItem> ...

instead of ArrayList, or, franky, in place of GroupItems {...}

Upvotes: 1

PenFold
PenFold

Reputation: 726

How about just replacing your GroupItems class with List<GroupItem<T>> ?

Upvotes: 0

madd0
madd0

Reputation: 9323

What I'd do is create a generic collection such as:

public class GroupItems<T> : List<GroupItem<T>>
{
}

If you need to extend the basic functionality of a list, you could also extend Collection<T> and override the methods you need:

public class GroupItems<T> : Collection<GroupItem<T>>
{
    protected override void InsertItem(int index, T item)
    {
         // your custom code here
         // ...

         // and the actual insertion
         base.InsertItem(index, item);
    }
}

Upvotes: 0

Related Questions