返回一个通用的 IEnumerable<T>

Posted

技术标签:

【中文标题】返回一个通用的 IEnumerable<T>【英文标题】:returning a generic IEnumerable<T> 【发布时间】:2012-07-11 14:05:22 【问题描述】:

我正在搞乱泛型和 IEnumerable,但我有点卡住了。 这是我正在尝试做的事情: 我想要一个返回任何集合类型的方法 - 实现 IEnumerable (?) - (例如:列表、堆栈、队列...)

此外,我希望能够返回任何数据类型的任何集合类型。 所以我希望这个方法能够返回一个List&lt;string&gt;,以及一个Stack&lt;int&gt;,以及一个List&lt;double&gt;...等等等等。

 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&lt;T&gt; 替换为 IEnumerable&lt;int&gt; ,我可以返回任何 int 类型的集合。然而这意味着,现在我不能再返回ListOfStrings了。

将不胜感激任何建议或想法 :)

【问题讨论】:

【参考方案1】:

您需要在方法中添加generic type parameter:

public IEnumerable<T> ReturnSomething<T>() 

    Stack<T> stackOfT = new Stack<T>();
    return stackOfT;

类型参数出现在方法名称之后,但在参数之前。也可以有一个具有多个类型参数的方法。

调用方法时可以指定类型:

IEnumerable<int> myInts = ReturnSomething<int>();

【讨论】:

谢谢,这确实有效,但现在我似乎无法向堆栈中添加任何内容..stackOfInts.Push(3);如果我尝试这个,它会说:“最好的重载匹配......有一些无效的参数”。有什么想法吗? @JaneDoe:您只能将Ts 添加到Stack&lt;T&gt;。 3 不一定是T。除非您添加 generic type constraint,否则您不知道 T 是什么,因此您甚至无法构建一个 - 为此您需要一个 new() 约束。你想做什么,为什么需要这个? 我不需要这个来做任何特别的事情,我只是在尝试一堆东西。不过我现在明白了,谢谢。【参考方案2】:

诀窍是声明 &lt;T&gt; 对,如果你定义了泛型&lt;T&gt;,那么你必须在你的方法中坚持它,所以如果你有IEnumerable&lt;T&gt;,那么在你的其他地方您必须使用 &lt;T&gt; 而不是 &lt;int&gt; 或任何其他类型的方法。

只有在你真正使用你的泛型类型时,你才会用泛型&lt;T&gt; 替换一个真正的类型。

查看示例

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】:
public IEnumerable<T> returnSomething() 

    Stack<int> stackOfInts = new Stack<int>();
    return (IEnumerable<T>) stackOfInts;

【讨论】:

【参考方案4】:

类型参数需要调用者在某处指定。

在实例化泛型类时:

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>())


【讨论】:

【参考方案5】:

更多帮助,完整结构如下...

我的模型是

  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 返回数据列表

 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;
        

最后一个是访问码

 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();

【讨论】:

【参考方案6】:

是的,如果您更改 IEnumerable&lt;T&gt; to IEnumerable&lt;dynamic&gt;,您可以返回任何类型

像这样:

public IEnumerable<dynamic> returnSomething() 

.....

【讨论】:

这确实有点像黑客。我试过了,它也没有编译。 @codesparkle 我同意你的观点并强烈遵循它,但是在他们无法控制给定的第三方 API 方法返回类型的时候,动态是这样的救星案例 @JaneDoe 当你调用这样的方法时: IEnumerable enumerable = returnSomething();它工作正常也请解释为什么它是一个黑客,我可能会学到一些新东西 “hack”可能有点强,我只是想指出codeparkle所说的。 对不起,我根本不捍卫动态,我只是想知道它可能会过度杀戮的原因

以上是关于返回一个通用的 IEnumerable<T>的主要内容,如果未能解决你的问题,请参考以下文章

返回 IEnumerable<T> 与 IQueryable<T>

返回 IEnumerable<T> 与 IQueryable<T>

使用 Linq 选择类的属性以返回 IEnumerable<T>

从 IEnumerable<T> 函数返回字符串

循环 IEnumerable<T> 抛出不支持的异常

使用 OrderByDescending 每一步返回 IEnumerable<T> 列表集合中的最大值