You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#遍历存储带参构造对象的ArrayList时无法读取对象属性问题

问题核心原因

ArrayList是.NET早期版本提供的非泛型集合,内部所有存储元素都会被视为object类型。你用var遍历集合时,item的编译时类型为object,而object类型并未定义Name属性——你当前能运行并输出类型全限定名,说明实际执行的代码是直接调用Console.WriteLine(item),此时方法会默认调用对象的ToString()实现,而object默认的ToString()方法返回值就是当前实例的类型全限定名。


推荐解决方案

现代C#开发中完全不建议使用ArrayList,应替换为泛型集合List<T>,它会在编译时校验元素类型,遍历取到的元素直接是目标类型,无装箱拆箱性能损耗,也不会出现类型访问错误。

  • 首先修改集合定义,注意访问修饰符需要匹配调用场景(Main方法中访问不能设为private):
// 位于Animal类中
public static List<Animal> AnimalList = new List<Animal>() 
{
    Duck.duck1,
    // 不需要提前定义静态字段,直接new带参构造的自定义对象即可
    new Duck("Donald", Gender.Male, 3)
};
  • 原有遍历逻辑无需修改即可正常运行,此时item会被自动推断为Animal类型,可直接访问Name属性:
public static void Main()
{
    foreach (var item in AnimalList)
        Console.WriteLine(item.Name);
}

运行后会按预期输出所有动物的Name属性值。


非推荐兼容方案(仅用于必须使用ArrayList的遗留场景)

如果因历史代码约束必须使用ArrayList,遍历元素时需要做显式类型转换,确认类型后再访问属性,避免运行时报错:

public static void Main()
{
    foreach (object rawItem in AnimalList)
    {
        if (rawItem is Animal animal)
        {
            Console.WriteLine(animal.Name);
        }
    }
}

相关疑问解答
  • 向集合(无论ArrayList还是泛型List)添加带参构造生成的自定义对象,不需要提前定义为静态字段,直接在集合初始化器或调用Add方法时传入new 类名(构造参数)即可,和普通场景下实例化对象没有区别。
  • ArrayList并非只能存储string、int等基础类型,它可以存储所有继承自object的类型实例,但因为没有编译时类型约束,很容易混入不符合预期的类型导致运行时错误,加上值类型存储时会产生装箱损耗,在C# 2.0推出泛型之后,所有新编写的业务代码都不应该再使用ArrayList,它目前仅用于兼容2005年之前的老版本.NET遗留代码。
  • 如果需要自定义类实例直接传入Console.WriteLine时的输出内容,可以在基类Animal中重写ToString()方法:
public override string ToString()
{
    return Name;
}

重写后哪怕不主动访问Name属性,直接输出对象本身也会返回Name值,而不是类型全限定名。

内容的提问来源于stack exchange,提问作者caxap

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 00:12:16