【问题标题】:How do you display items from a list in a message box?如何在消息框中显示列表中的项目?
【发布时间】:2013-05-31 23:47:13
【问题描述】:

我正在开展一个项目,该项目需要显示收入高于平均水平的人员列表。源数据是 List<IncomeData>(id 是此人的唯一 ID):

public struct IncomeData
{
    public string id;
    public double household;
    public income;
}

public double belowAverage = 0, total, belowAveragePercent;

IncomeData surveyStruct;
List<IncomeData> surveyList = new List<IncomeData>();
List<string> aboveAverage = new List<string>();

以下是我如何确定一个人的收入是否高于平均水平。如果一个人的收入高于平均水平,我将 surveyStruct 的临时实例中的 id 和 income 添加到上述平均字符串值列表中:

//Determine poverty.
if (surveyStruct.income - 3480 * surveyStruct.household <= 6730)
{
    belowAverage += 1;
}
else if (surveyStruct.income - 3480 * surveyStruct.household >= 6730)
{
    aboveAverage.Add(surveyStruct.id);
    aboveAverage.Add(surveyStruct.income.ToString());
}

这是在消息框中显示所需信息的代码。 (这里也添加了aboveAverage 列表。)

private void reportsToolStripMenuItem_Click(object sender, EventArgs e)
{
    //Display reports 1, 2, and 3.
    MessageBox.Show("Your Entry:\nID Code: " + surveyStruct.id +
       "\nHousehold: " + surveyStruct.household.ToString() +
       " people\nIncome: " + surveyStruct.income.ToString("C") +
       "\n\nPeople Above Average:\n" + aboveAverage +
       "\n\nAnd " + belowAveragePercent + "% of people are below average.");
    }

现在,问题来了: 我看到的不是在消息框中的值列表,而是在System.Collections.Generic.List`1[System.String] 上面的普通人的 ID 和收入应该是。有人可以告诉我我做错了什么以及如何在消息框中显示列表值吗?

【问题讨论】:

    标签: c# list struct messagebox


    【解决方案1】:

    在问题的最后,您问:如何在消息框中显示List&lt;IncomeData&gt;?

    因此,您问题的核心是将值列表转换为字符串,以便您可以将该字符串作为参数传递给MessageBox.Show()。

    LINQ 扩展方法Enumerable.Aggregate() 为这个问题提供了理想的解决方案。假设您的 List&lt;IncomeData&gt; 看起来像这样(为简洁起见,我省略了 household 字段):

    var incomes = new List<IncomeData>() {
        new IncomeData("abc0123", 15500),
        new IncomeData("def4567", 12300),
        new IncomeData("ghi8901", 17100)
    };
    

    以下 LINQ 查询会将 List&lt;IncomeData&gt; 转换为 string:

    string message = incomes.
        Select(inc => inc.ToString()).
        Aggregate((buffer, next) => buffer + "\n" + next.ToString());
    

    要消除调用Select() 的需要,您可以改用Enumerable.Aggregate() 的两个参数版本。这种方法还允许您将标题指定为累加器的种子值:

    string message2 = incomes.
        Aggregate(
            "Income data per person:",
            (buffer, next) => buffer + "\n" + next.ToString());
    

    这等效于以下参数类型已明确的情况:

    string message = incomes.
        Aggregate<IncomeData, string>(
            "Income data per person:",
            (string buffer, IncomeData next) => buffer + "\n" + next.ToString());
    

    请参阅以下内容(和online demo)以获取完整的工作示例,前面是其预期输出。

    预期输出

    Income data per person:
    Id: abc0123, Income:15500
    Id: def4567, Income:12300
    Id: ghi8901, Income:17100
    

    演示程序

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace LinqAggregateDemo
    {
        public class Program
        {
    
            public static void Main(string[] args)
            {            
                var incomes = new List<IncomeData>() {
                    new IncomeData("abc0123", 15500),
                    new IncomeData("def4567", 12300),
                    new IncomeData("ghi8901", 17100)
                };
    
                string message = incomes.
                    Select(inc => inc.ToString()).
                    Aggregate((buffer, next) => buffer + "\n" + next.ToString());
    
                Console.WriteLine("Income data per person:\n" + message);
            }
    
            public struct IncomeData
            {
                public readonly string Id;
                public readonly int Income;
    
                public IncomeData(string id, int income)
                {
                    this.Id = id;
                    this.Income = income;
                }
    
                public override string ToString()
                {
                    return String.Format(
                        "Id: {0}, Income:{1}",
                        this.Id,
                        this.Income);
                }
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      首先,将 aboveAverage 设为 List&lt;IncomeData&gt;,并将匹配的收入数据添加到该列表中。

      然后,您需要为您的自定义结构定义一个ToString,如下所示:

      public override void string ToString()
      {
        return string.Format("The id is {0}, the household is {1} and the income is {2}.", id, household, income);
      }
      

      然后,在 MessageBox.Show 调用中,您需要将 aboveAverage 替换为

      aboveAverage.Aggregate((a,b) => a.ToString() + Enviroment.NewLine + b.ToString())
      

      应该让它正确显示。

      抱歉格式问题,我在移动设备上。

      【讨论】:

        【解决方案3】:

        StringBuilder 是一种选择:

            StringBuilder aboveAverage = new StringBuilder();
        
            //Determine poverty.
             if (surveyStruct.income - 3480 * surveyStruct.household <= 6730)
            {
                belowAverage += 1;
            }
            else if (surveyStruct.income - 3480 * surveyStruct.household >= 6730)
            {
                aboveAverage.Append(string.Format("id: %s, income: %s\n",
                        surveyStruct.id, surveyStruct.income.ToString());
            }
        

        您将需要一个 ToString() 用于字符串构建器,如下所示:

            MessageBox.Show("Your Entry:\nID Code: " + surveyStruct.id + "\nHousehold: " + surveyStruct.household.ToString() + " people\nIncome: " + surveyStruct.income.ToString("C") + "\n\nPeople Above Average:\n" + aboveAverage.ToString() + "\n\nAnd " + belowAveragePercent + "% of people are below average.");
        

        如果您将 aboveAverage 保留为列表,则可以使用 join 来完成,如下所示:

         string.Join(aboveAverage,Environment.NewLine);
        

        在您当前的代码中——但这看起来不太好。

        你也可以用 Linq 来做,你想看看吗?

        好的,这是一个性感的单行版本:(所有问题都应该有一个单行 linq 答案):

        (使用和缩进不算,它们只是为了使代码更具可读性!)

        using NL = Environment.NewLine;
            
        string indent = "    ";
        
        MessageBox.Show(
          "Your Entry:" + NL +
          "ID Code: " + surveyStruct.id +  NL +
          "Household: " + surveyStruct.household.ToString() + " people" + NL +
          "Income: " + surveyStruct.income.ToString("C") + NL + NL +
          "People Above Average:"  + NL +
             indent + string.Join(NL+indent,
                                  surveyList.Where(s => (s.income - 3480) * s.household >= 6730)
                                            .Select(s => "ID: "+s.id+" $"+s.income.ToString).ToArray()) + NL +
                 "And " + (surveyList.Where(s => ((s.income - 3480) * s.household) <= 6730).Count() / surveyList.Count()) * 100 + "% of people are below average.");
        

        【讨论】:

        • @Hogan 如果我使用 Linq 会有什么不同吗?
        • @chotto-motto - 只有一行!
        猜你喜欢
        • 1970-01-01
        • 2012-04-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多