ehcanadian
ehcanadian

Reputation: 1784

How to return a generic list?

I don't even think I have the question correct as I am just starting with generics and my knowledge isn't very great.

Say I have the following method:

public class Wrapper
{
    public List<TInfoType> GetInfo<TInfoType>(Array data, EdmCmd edmCmd)
    {
        switch (edmCmd.meCmdType)
        {
        case EdmCmdType.EdmCmd_PostAdd:
            List<EdmCmdPostAddInfo> info = new List<EdmCmdPostAddInfo>();
            foreach (EdmCmdData item in data)
            {
                info.Add(new EdmCmdPostAddInfo(item.mlObjectID1, item.mlObjectID2, item.mbsStrData1, item.mlLongData1));
            }
            return info;
            break;                
        default:
            break;
        }
    }
}

And I would like to call the method like:

List<EdmCmdPostAddInfo> info = wrapper.GetInfo<EdmCmdPostAddInfo>(data, edmCmd)

What is the correct way to do this? I am getting the error:

Cannot implicitly convert type 'System.Collections.Generic.List<EPDM.Utils.EdmCmdPostAddInfo>' to 'System.Collections.Generic.List<TInfoType>'

I am doing this because the EdmCmd struct that is passed to the method has various members that are generically named. It's difficult to remember what the members represent for each CmdType, so I am wrapping them in a more meaningful struct.

Upvotes: 2

Views: 4564

Answers (4)

Robert Rossney
Robert Rossney

Reputation: 96722

The fact that you're referencing a type explicitly in your generic method indicates that you've got trouble. There's no way for the compiler to know that a List<T> can contain an object of some type unless that type is T.

So create your list like this:

result = new List<T>();
foreach (EdmCmdData item in data)
{
   object o = new EdmCmdPostAddInfo(item.mlObjectID1, item.mlObjectID2, item.mbsStrData1, item.mlLongData1)
   result.Add((T)s);
}
return result;

This will throw an InvalidCastException at runtime if you invoke the method with the wrong type, but that's a problem you should already be expecting to have.

Upvotes: 1

Brett
Brett

Reputation: 11

public class Wrapper
{
   public List<TInfoType> GetInfo<TInfoType>(Array data, EdmCmd edmCmd)
   {
      List<object> info = new List<object>();

      switch (edmCmd.meCmdType)
      {
        case EdmCmdType.EdmCmd_PostAdd:
          foreach (EdmCmdData item in data)
          {
            info.Add(new EdmCmdPostAddInfo(item.mlObjectID1, item.mlObjectID2, item.mbsStrData1, item.mlLongData1));
          }
          break;                
        default:
          break;
      }

      return info.OfType<TInfoType>().ToList();
   }
}

Assuming all of your new ECmd* structures are truly structs and not classes with a hierarchy, you can create a List of objects and cast this after you've processed the passed in array.

Upvotes: 1

Nestor
Nestor

Reputation: 13990

if you use

TInfoType[] data

instead of

Array data

as the parameter, then you can use

List<TInfoType> info = new List<TInfoType>();

intead of

List<EdmCmdPostAddInfo> info = new List<EdmCmdPostAddInfo>();            

and then you don't need to do the new (instead you just use the objects passed in data). I hope this gives you the starting point.

Upvotes: 2

Dave Markle
Dave Markle

Reputation: 97691

I think I see what you're trying to do, and it's not really possible to do it like you want to in C# 3 and previous version. This is a feature of C# 4 though, but you'll have to wait for a few months for that to go RTM.

Upvotes: 0

Related Questions