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

为何结构体列表无法作为IEnumerable<object>?

问题解析:结构体列表无法转换为IEnumerable<object>的原因

运行以下程序会得到如下输出:

Class is object.
Class list is IEnumerable.
Struct is object.
Struct list is not IEnumerable.

这表明结构体实例可以被视为object类型,但结构体实例的列表却不能被视为IEnumerable<object>。这是为什么?

测试代码

using System;
using System.Collections.Generic;

public class Program
{
    public struct MyStruct
    {}
    
    public class MyClass
    {}
    
    public static void Main()
    {
        // 检查类实例是否属于object类型
        MyClass classInstance = new MyClass();
        if (classInstance is object) Console.WriteLine("Class is object.");
        else Console.WriteLine("Class is no object.");
        
        // 检查类实例列表是否属于IEnumerable<object>
        List<MyClass> classList = new List<MyClass>() {classInstance};
        if (classList is IEnumerable<object>) Console.WriteLine("Class list is IEnumerable<object>");
        else Console.WriteLine("Class list is not IEnumerable<object>");

        // 检查结构体实例是否属于object类型
        MyStruct structInstance = new MyStruct();
        if (structInstance is object) Console.WriteLine("Struct is object.");
        else Console.WriteLine("Struct is no object.");
        
        // 检查结构体列表是否属于IEnumerable<object>
        List<MyStruct> structList = new List<MyStruct>() {structInstance};
        if (structList is IEnumerable<object>) Console.WriteLine("Struct list is IEnumerable<object>");
        else Console.WriteLine("Struct list is not IEnumerable<object>");       
        
        Console.ReadLine();
    }
}

原因分析

  1. 单个值类型的装箱操作
    结构体是值类型,object是所有.NET类型的基类。当把单个值类型实例和object做类型检查时,CLR会自动执行装箱操作:把值类型的数据复制到堆上的对象实例中,因此structInstance is object会返回true。

  2. 泛型协变的类型限制
    IEnumerable<T>是带out T标记的协变泛型接口,协变允许将IEnumerable<派生类型>隐式转换为IEnumerable<基类型>,但这个特性只支持引用类型,不支持值类型:

    • 对于引用类型MyClass,List<MyClass>实现了IEnumerable<MyClass>,由于协变特性,它可以直接被视为IEnumerable<object>——毕竟引用类型的转换只是指向对象的引用变化,不需要复制数据。
    • 对于值类型MyStruct,如果要让List<MyStruct>转为IEnumerable<object>,意味着列表里的每个元素都需要单独装箱,但协变机制无法自动完成这种批量转换(会带来额外性能开销和类型安全风险),因此CLR直接禁止了值类型的协变转换,所以structList is IEnumerable<object>返回false。

如果需要把结构体列表转为IEnumerable<object>,可以手动调用Cast<object>()方法完成批量装箱:

if (structList.Cast<object>() is IEnumerable<object>) 
    Console.WriteLine("Struct list can be cast to IEnumerable<object>");

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 02:07:21