Возвращая общий IEnumerable <T>
Я возился с дженериками, и IEnumerable abit, но я доволен.
Вот что я пытаюсь сделать:
Я хочу иметь метод, который возвращает любой тип коллекции - который реализует IEnumerable (?) - (так, например, List, Stack, Queue,...)
Кроме того, я хочу иметь возможность возвращать любой тип коллекции любого типа данных.
поэтому я хочу, чтобы этот метод мог возвращать List<string>,
, а также Stack<int>
, а также List<double>
... и т.д. и т.д.
public IEnumerable<T> returnSomething()
{
Stack<int> stackOfInts = new Stack<int>();
List<string> listOfStrings = new List<string>();
return stackOfInts;
}
Это то, что я пробовал до сих пор. это, однако, не работает, я получаю эту ошибку:
Cannot implicitly convert type 'System.Collections.Generic.Stack<int>' to 'System.Collections.Generic.IEnumerable<T>'. An explicit conversion exists (are you missing a cast?)
однако, если я заменил IEnumerable<T>
в сигнатуре метода на IEnumerable<int>
, я могу вернуть любую коллекцию типа int. Однако это означает, что теперь я больше не могу вернуть ListOfStrings
.
по достоинству оценят любые предложения или идеи:)
Ответы
Ответ 1
Вам необходимо добавить общий тип параметра к вашему методу:
public IEnumerable<T> ReturnSomething<T>()
{
Stack<T> stackOfT = new Stack<T>();
return stackOfT;
}
Параметр type появляется после имени метода, но перед параметрами. Также возможно иметь метод с более чем одним параметром типа.
При вызове метода вы можете указать тип:
IEnumerable<int> myInts = ReturnSomething<int>();
Ответ 2
Фокус в объявить <T>
вправо, если вы определяете общий <T>
, тогда вы должны придерживаться его в своих методах, поэтому, если у вас есть IEnumerable<T>
, то в другом месте вашего вы должны использовать <T>
, а не <int>
или любой другой тип.
Только последний, когда вы на самом деле используете, вы используете общий тип, который подставляет общий <T>
для реального типа.
См. образец
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();
}
}
Ответ 3
Да, вы можете вернуть любой тип, если вы меняете я Enumerable<T> to IEnumerable<dynamic>
вот так:
public IEnumerable<dynamic> returnSomething()
{
.....
Ответ 4
public IEnumerable<T> returnSomething()
{
Stack<int> stackOfInts = new Stack<int>();
return (IEnumerable<T>) stackOfInts;
}
Ответ 5
Параметр типа должен быть указан вызывающим пользователем где-то.
Либо при создании экземпляра класса generic:
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())
{
}
Или при вызове общего метода не-общего класса:
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>())
{
}