【问题标题】:returning a generic IEnumerable<T>返回一个通用的 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了。

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

【问题讨论】:

    标签: c# generics ienumerable


    【解决方案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所说的。
            • 对不起,我根本不捍卫动态,我只是想知道它可能会过度杀戮的原因
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多