28

I want to have a method that returns any collection type - that implements IEnumerable (?) - (so e.g: List, Stack, Queue, ...)

Furthermore it should return any collection type, of any datatype. so i want this method to be able to return a List<string>, as well as a Stack<int>, as well as a List<double>... etc etc.

 public IEnumerable<T> returnSomething() 
    {
        Stack<int> stackOfInts = new Stack<int>();
        List<string> listOfStrings = new List<string>();
        return stackOfInts;
    }

this is what i've tried so far. this however doesn't work, i get this error:

Cannot implicitly convert type 'System.Collections.Generic.Stack<int>' to 'System.Collections.Generic.IEnumerable<T>'. An explicit conversion exists (are you missing a cast?)

however, if i replace the IEnumerable<T> in the method signature to IEnumerable<int> , i can return any collection of type int. This however means, that now i can't return the ListOfStrings anymore.

How can I resolve this?

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
Thousand
  • 6,562
  • 3
  • 38
  • 46

6 Answers6

35

You need to add a generic type parameter to your method:

public IEnumerable<T> ReturnSomething<T>() 
{
    Stack<T> stackOfT = new Stack<T>();
    return stackOfT;
}

The type parameter appears after the method name, but before the parameters. It is also possible to have a method with more than one type parameter.

When you call the method you can specify the type:

IEnumerable<int> myInts = ReturnSomething<int>();
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • thanks, this works indeed, but now i cant seem to add anything to the stack..stackOfInts.Push(3); if i try this, it says: "the best overloaded match .. has some invalid arguments". any ideas? – Thousand Jul 11 '12 at 21:08
  • @JaneDoe: You can only add `T`s to a `Stack`. 3 isn't necessarily a `T`. Unless you add a [generic type constraint](http://msdn.microsoft.com/en-us/library/d5x73970.aspx) you have no idea what a `T` is, so you can't even construct one - to do that you'd need a `new()` constraint. What are you trying to do, and why do you need this? – Mark Byers Jul 11 '12 at 21:10
  • 1
    i dont need this for anything in particular, im just trying out a bunch of things. But i get it now, thank you. – Thousand Jul 11 '12 at 21:12
11

The trick is to declare <T> right, if you define generic <T>, then you have to stick to it in your methods, so if you have IEnumerable<T> then elsewhere in your method you must use <T> and not <int> or any other type.

It is only latter when you actually use you generic type you substitute generic <T> for a real type.

See a sample

class Foo<T>
{
    public IEnumerable<T> GetList()
    {
        return new List<T>();
    }

    public IEnumerable<T> GetStack()
    {
        return new Stack<T>();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Foo<int> foo = new Foo<int>();
        IEnumerable<int> list = foo.GetList();
        IEnumerable<int> stack = foo.GetStack();

        Foo<string> foo1 = new Foo<string>();
        IEnumerable<string> list1 = foo1.GetList();
        IEnumerable<string> stack1 = foo1.GetStack();
    }
}
oleksii
  • 35,458
  • 16
  • 93
  • 163
3
public IEnumerable<T> returnSomething() 
{
    Stack<int> stackOfInts = new Stack<int>();
    return (IEnumerable<T>) stackOfInts;
}
burning_LEGION
  • 13,246
  • 8
  • 40
  • 52
2

The type parameter needs to be specified by the caller somewhere.

Either when instantiating a generic class:

public class MyClass<T>
{
    public IEnumerable<T> returnSomething()
    {
        Stack<T> stackOfTs = new Stack<T>();
        List<T> listOfTs = new List<T>();
        return stackOfTs;
    }
}

var v = new MyClass<int>();
foreach(var item in v.returnSomething())
{
}

Or when calling a generic method of a non-generic class:

public class MyClass
{
    public IEnumerable<T> returnSomething<T>()
    {
        Stack<T> stackOfTs = new Stack<T>();
        List<T> listOfTs = new List<T>();
        return stackOfTs;
    } 
}


var v = new MyClass();
foreach(var item in v.returnSomething<int>())
{
}
Joe
  • 122,218
  • 32
  • 205
  • 338
2

For more help full structure given below ...

my model is

  public class Student
{
    public int studentId { get; set; }
    public string studentName { get; set; }
    public string subject { get; set; }
    public string studentClass { get; set; }
    public int RollNumber { get; set; }

}

IEnumerable return datalist

 public static IEnumerable<Student> ReturnSomething()
        {
            IList<Student> studentList = new List<Student>()
            {
                new Student()
                    {studentId = 1, studentName = "Bill", subject = "Science", studentClass = "nine", RollNumber = 01},
                new Student()
                    {studentId = 2, studentName = "Steve", subject = "Arts", studentClass = "ten", RollNumber = 03},
                new Student()
                    {studentId = 3, studentName = "Ram", subject = "Commerce", studentClass = "nine", RollNumber = 05},
                new Student()
                    {studentId = 1, studentName = "Moin", subject = "Science", studentClass = "ten", RollNumber = 06}
            };

            return studentList;
        }

and last one is access code

 Student student = new Student();
 IEnumerable<Student> studentList = ReturnSomething();

        foreach (Student VARIABLE in studentList)
        {
            student.studentName += VARIABLE.studentName + " "+ "Class= ";
            student.studentClass += VARIABLE.studentClass + " ";
        }

        Console.WriteLine(student.studentName + student.studentClass);
        Console.ReadKey();
0

Yes you can return any type if you change IEnumerable<T> to IEnumerable<dynamic>

like this:

public IEnumerable<dynamic> returnSomething() 
{
.....
HatSoft
  • 11,077
  • 3
  • 28
  • 43
  • this indeed seems like a bit of a hack.. i tried it and it also didnt compile. – Thousand Jul 11 '12 at 21:16
  • @codesparkle I agree with your point and strongly follow it too, but their are times when you don't have control on the given third party API method return type, so dynamic is the saviour in such a case – HatSoft Jul 11 '12 at 21:18
  • @JaneDoe when you make call the method like this : IEnumerable enumerable = returnSomething(); it works fine also please explain why it is a hack, I might learn something new – HatSoft Jul 11 '12 at 21:22
  • "hack" might've been a bit strong, i was merely trying to point out what codesparkle said. – Thousand Jul 11 '12 at 21:25
  • Sorry guys im not defending dynamic at all, I just want to know the reasons when it can be an over kill – HatSoft Jul 11 '12 at 21:28