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

C#实现通用方法:无需指定属性即可打印LINQ结果到控制台

搞定任意类集合的属性值打印问题

我懂你想要的效果——一个万能方法,不管用LINQ查出来的是什么类的集合,都能把所有属性名和对应值整齐打印到控制台。之前用反射的思路是对的,问题出在没用到泛型来适配任意类型,导致参数没法灵活支持var声明的变量。

直接上完整的解决方案代码,你可以直接复用:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

public static class CollectionPrinter
{
    // 泛型方法,支持任意类型的枚举集合
    public static void PrintTable<T>(IEnumerable<T> items)
    {
        if (items == null || !items.Any())
        {
            Console.WriteLine("集合为空或不存在");
            return;
        }

        // 获取当前类型的所有公共实例属性
        PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        if (properties.Length == 0)
        {
            Console.WriteLine("该类型没有公共属性");
            return;
        }

        // 打印表头:左对齐固定宽度20,保证排版整齐
        foreach (var prop in properties)
        {
            Console.Write($"{prop.Name,-20}");
        }
        Console.WriteLine();
        Console.WriteLine(new string('-', properties.Length * 20)); // 打印分隔线

        // 遍历每个元素,打印对应属性值
        foreach (var item in items)
        {
            foreach (var prop in properties)
            {
                var value = prop.GetValue(item) ?? "null"; // 处理null值,避免空输出
                Console.Write($"{value.ToString(),-20}");
            }
            Console.WriteLine();
        }
    }
}

// 测试用例类
public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public DateTime JoinDate { get; set; }
}

public class Product
{
    public string ProductId { get; set; }
    public string ProductName { get; set; }
    public decimal Price { get; set; }
    public bool InStock { get; set; }
}

class Program
{
    static void Main()
    {
        // 用LINQ筛选Person集合
        var people = new List<Person>
        {
            new Person { Id = 1, Name = "Alice", Age = 28, JoinDate = new DateTime(2022, 3, 15) },
            new Person { Id = 2, Name = "Bob", Age = 35, JoinDate = new DateTime(2021, 10, 20) }
        }.Where(p => p.Age > 30);

        Console.WriteLine("===== Person集合打印结果 =====");
        CollectionPrinter.PrintTable(people);

        // 用LINQ筛选Product集合
        var products = new List<Product>
        {
            new Product { ProductId = "P001", ProductName = "Laptop", Price = 999.99m, InStock = true },
            new Product { ProductId = "P002", ProductName = "Mouse", Price = 25.5m, InStock = false }
        }.Where(p => p.Price < 100);

        Console.WriteLine("\n===== Product集合打印结果 =====");
        CollectionPrinter.PrintTable(products);
    }
}

核心细节说明:

  • 泛型适配任意类型:PrintTable<T>接收IEnumerable<T>参数,不管你用var声明的是List<Person>还是LINQ返回的IQueryable<Product>,都能完美兼容,这就是你要的“支持var”的关键。
  • 反射获取属性:用typeof(T).GetProperties()获取泛型类型的公共属性,保证表头和每行的属性一一对应。如果需要包含非公共属性,可以调整BindingFlags参数(比如加上BindingFlags.NonPublic)。
  • null值友好处理:用?? "null"把null值转换成可读性强的字符串,避免控制台出现空白。
  • 排版优化:通过-20实现左对齐并固定宽度,让输出的表格整齐易读。

你之前可能踩的坑:

如果之前的方法没用到泛型,而是用object或特定类型做参数,就没法灵活接收各种LINQ查询结果;另外如果用item.GetType().GetProperties(),当集合里有派生类实例时,会打印派生类的额外属性,而用typeof(T)则会严格按照声明的类型打印属性,你可以根据需求选择。

如果需要更定制化的效果(比如跳过某些属性、格式化日期/数字),还可以给方法加参数或者用特性标记来控制,这个基础版本已经能满足大部分场景啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:31:36