【问题标题】:Method is returning List when the method return type IEnumerable.But GetType shows as List当方法返回类型 IEnumerable 时,方法返回 List。但 GetType 显示为 List
【发布时间】:2019-02-04 04:57:13
【问题描述】:

虽然,下面的问题似乎很愚蠢,但它仍然可以帮助其他人。我有返回列表的方法。方法返回类型为 IEnumnerable。 方法:

public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public static IEnumerable<Person> GetPersons()
        {
            List<Person> personList = new List<Person>()
                                          {
                                              new Person() { Age = 10, Name = "Vijay"}
                                          };

           return personList;

        }
    }

现在每当我调用这个方法并检查类型。输出是

System.Collections.Generic.List

因为它是一个列表。我应该能够将项目添加到列表中。但是系统抛出编译错误。 下面是执行部分:

public class Program
    {
        public static void Main(string[] ar)
        {
            var personList = Person.GetPersons();
            Console.WriteLine(personList.GetType()); //System.Collections.Generic.List
            personList.Add(new Person(){Age = 11, Name = "Ajay"}); // Compilation error
            Console.ReadKey();

        }
    }

所以任何人都可以帮助我理解。这将是很大的帮助。 提前致谢。

【问题讨论】:

  • 看看How can I add an item to a IEnumerable<T> collection?....它可能会帮助你理解。
  • IEnumerable 视为底层类型(即列表)之上的掩码。我的意思是物理面具(如达斯维德的面具)。可枚举的 itself 知道它是什么(即它知道它是一个列表)。但是它的 caller / user 没有。所以调用者/用户只能使用 all ienumerables 可用的方法与 ienumerable 交互。为什么编译器会这样工作?好吧,仅仅因为面具后面的东西是今天 List 并不意味着它永远都是。明天,实现可能会改变——它可能是一个数组(不支持Add)。
  • 但是每当调用者调用方法并获取方法的类型时。它仍然显示为 System.Collections.Generic.List 。你能解释为什么 GetType 显示为 List
  • 因为你在问对象它到底是什么。在运行时,它知道面具下是什么(就像如果你戴上达斯维德面具并且有人问你的名字 - 你知道你的名字,但与你交谈的人不知道,除非你告诉他们——这基本上就是GetType 正在做的事情)。但是编译器不知道在 编译时 - 它看到的只是掩码(可能是你在掩码中,或者我 - 它无法区分)。
  • 您遇到的问题与dotnetfiddle.net/ol898U 显示的问题基本相同。请注意,您和我都知道bobstring - 但编译器不知道(它认为类型是object,因为这是变量的类型)。所以它不会让我使用bob.Length,因为object 没有Length 属性。这与您所看到的基本相同(除了string 类似于Listobject 类似于IEnumerable)。但是,就像IEnumerable 一样,如果您调用bob.GetType(),它将返回string

标签: c# generics collections


【解决方案1】:

IEnumerable Interface

公开枚举器,它支持一个简单的迭代 指定类型的集合。

就是这样,就是这样。现在,有很多扩展方法可以与IEnumerable 一起使用,尽管Add 不是其中之一

List&lt;T&gt;,实现了IEnumerable,这是有道理的,它有添加的能力。

所以从这里你有两个选择

  1. 返回List&lt;T&gt;

    • public static List&lt;Person&gt; GetPersons()
  2. 将您的IEnumerable 枚举为List&lt;T&gt;

    • var personList = Person.GetPersons().ToList();

你应该使用哪一个?好吧,事实上您正在尝试添加一些东西,而您只是没有枚举它,或者在 Linq 语句中使用它,这表明您可能应该使用选项 1


但是每当调用者调用该方法并获取该方法的类型时 方法。它仍然显示为 System.Collections.Generic.List 。可以 你解释了为什么 GetType 显示为 List

因为这是创建的类型,所以当您返回 IEnumerable 时,您只是将 List&lt;T&gt; 转换为更基本的类型(在本例中为接口)。当您调用 GetType 时,它会告诉您它是什么类型,因为它IS 是那种类型。编译器仍然知道您创建的类型!以防万一你想把它扔回去。

我认为您需要更多地阅读文档

【讨论】:

    【解决方案2】:

    IEnumerable 接口负责迭代集合,而不是存储和添加/删除。因此,要启用添加到列表,您可以将返回类型更改为 List&lt;Person&gt;,如下所示:

    public static List<Person> GetPersons()
    [...]
    

    一切都应该正常。

    虽然您的返回方法确实返回了一个列表,但通过说返回类型是一个 IEnumerable,您是在对函数的用户说应该只迭代,而不是改变。这也是您收到编译错误的原因。

    【讨论】:

      【解决方案3】:

      IEnumerable 不支持添加新元素。

      IEnumerable 来自 MSDN 的接口:

      公开一个枚举器,它支持对非泛型集合的简单迭代。

      不要使用IEnumerable&lt;Person&gt; 作为GetPerson() 函数的返回类型,而是使用List&lt;Person&gt;

      喜欢

          public static List<Person> GetPersons()
          {
              List<Person> personList = new List<Person>()
                                            {
                                                new Person() { Age = 10, Name = "Vijay"}
                                            };
      
             return personList;
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-07-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-11
        • 2019-05-11
        • 1970-01-01
        相关资源
        最近更新 更多