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

如何修复含Distinct()的LINQ表达式编译错误?

问题描述

我正在开发一个C#控制台应用程序,将.CSV文件的数据读取到自定义对象列表中,并用LINQ进行处理。程序大部分编译正常,但在两处提取唯一值并写入文本文件的代码行出现编译错误。

具体来说,IDE在我尝试使用.Distinct()和.ForEach()的LINQ链末尾抛出编译错误。有趣的是,代码中之前使用számlák.Select(x => x.PályázatKód).Distinct().Count()的类似查询完全正常,但当我尝试用StreamWriter遍历去重值写入文件时,编译器拒绝执行。错误似乎出现在Distinct().ForEach(...)的转换环节,但我无法确定具体的类型不匹配或缺失引用问题。

背景信息:我的Szamla类已正确定义,包含标准自动实现属性和可用构造函数。数据已从szamlak.csv文件正确读取,Count()和Sum()等操作执行正常,且文件顶部已引入System.Linq命名空间。

我对Distinct()向下传递数据的机制有什么误解?如何正确遍历过滤后的结果写入输出文件?

Szamla类代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VizsgaKonzol
{
    internal class Szamla
    {
        private string pályázatKód;
        private string számlaszám;
        private string dátum;
        private int érték;
        private string költségTípus;

        public string PályázatKód { get => pályázatKód; set => pályázatKód = value; }
        public string Számlaszám { get => számlaszám; set => számlaszám = value; }
        public string Dátum { get => dátum; set => dátum = value; }
        public int Érték { get => érték; set => érték = value; }
        public string KöltségTípus { get => költségTípus; set => költségTípus = value; }

        public Szamla(string pályázatKód, string számlaszám, string dátum, int érték, string költségTípus)
        {
            this.pályázatKód = pályázatKód;
            this.számlaszám = számlaszám;
            this.dátum = dátum;
            this.érték = érték;
            this.költségTípus = költségTípus;
        }

        public override string ToString()
        {
            return $"{pályázatKód}: {dátum} - {érték} Ft - {számlaszám} - {költségTípus}";
        }
    }
}
Program.cs代码
using System.IO;
using VizsgaKonzol;

List<Szamla> számlák = new List<Szamla>();

using (StreamReader reader = new StreamReader("szamlak.csv"))
{
    reader.ReadLine();

    while (!reader.EndOfStream)
    {
        string[] line = reader.ReadLine().Split(';');
        számlák.Add(new Szamla(line[0], line[1], line[2], int.Parse(line[3]), line[4]));
    }
}

var a = számlák.OrderBy(x => x.PályázatKód);

Console.WriteLine("3. feladat:\n\tA fájl beolvasása és eltárolása kész.");
Console.WriteLine($"4. feladat:\n\tA fájlban lévő számlák darabszáma: {számlák.Count}.");
Console.WriteLine($"5. feladat:\n\tA számlák összértéke: {számlák.Sum(x => x.Érték).ToString("##,#")} Ft.");
Console.WriteLine($"6. feladat:\n\t{számlák.Select(x => x.PályázatKód).Distinct().Count()} db különböző pályázat készült.");

using (StreamWriter sw = new StreamWriter("kodok.txt"))
{
    // 原错误代码:számlák.OrderBy(x => x.PályázatKód).Select(x => x.PályázatKód).Distinct().ForEach(x => sw.Write($"{x}\n"));
    // 修正方式1:转为List后调用ForEach
    számlák.OrderBy(x => x.PályázatKód).Select(x => x.PályázatKód).Distinct().ToList().ForEach(x => sw.WriteLine(x));
}

Console.WriteLine("3. feladat:\n\tA kodok.txt fájl kész.");

using (StreamWriter sw = new StreamWriter("koltseg_tipusok.txt"))
{
    // 同样修正
    számlák.OrderBy(x => x.KöltségTípus).Select(x => x.KöltségTípus).Distinct().ToList().ForEach(x => sw.WriteLine(x));
}

Console.WriteLine("3. feladat:\n\tA koltseg_tipusok.txt fájl kész.");

Console.Write("9. feladat:\n\tAdja meg a keresett pályázat sorszámát: ");
string beker = Console.ReadLine();

if (beker.Length > 3)
{
    Console.WriteLine("nem megfelelő számformátum, max 3 jegyű lehet!");
}
else
{
    string nulla = "";

    for (int i = 0; i < 3 - beker.Length; i++)
    {
        nulla += "0";
    }

    nulla += beker;
    beker = nulla;
}

List<Szamla> szűrt = számlák.Where(x => x.PályázatKód == $"P-{beker}").OrderBy(x => x.Dátum).ToList();

if (szűrt.Count > 0)
{
    szűrt.ForEach(x => Console.WriteLine($"\t{x.ToString()}"));
    Console.WriteLine($"\tÖsszesen {szűrt.Count} db számla tartozik hozzá.");
}
else 
{
    Console.WriteLine($"\tNincs ilyen pályázat: P-{beker}!"); 
}
问题原因及解决方案

核心原因

Distinct()方法返回的是IEnumerable<T>类型,而**IEnumerable<T>并没有内置的ForEach()方法**——你之前能用ForEach()是因为调用的是List<T>的实例方法,而LINQ链式调用到Distinct()之后已经不再是List<T>类型了。

之前的Count()能正常工作,是因为Count()是LINQ为IEnumerable<T>提供的扩展方法,和List<T>的Count属性/方法是两回事。

两种修正方式

  1. 转换为List后调用ForEach
    在Distinct()之后追加.ToList(),将IEnumerable<T>转换为List<T>,这样就能调用List<T>的ForEach()实例方法:
    számlák.OrderBy(x => x.PályázatKód).Select(x => x.PályázatKód).Distinct().ToList().ForEach(x => sw.WriteLine(x));
    
  2. 使用标准foreach循环
    直接遍历IEnumerable<T>结果,这也是更符合C#常规写法的方式:
    foreach (var kod in számlák.OrderBy(x => x.PályázatKód).Select(x => x.PályázatKód).Distinct())
    {
        sw.WriteLine(kod);
    }
    

额外注意点

原Program.cs代码中缺少System.IO命名空间的引用,StreamReader和StreamWriter需要这个命名空间才能正常编译,记得添加:

using System.IO;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.02 02:44:52