首页 > 解决方案 > C# foreach 循环通过未知类型的集合

问题描述

我有一个通用方法,可以用 2 种不同的对象类型 TypeA 或 TypeB 调用。TypeA 和 TypeB 本质上是相同的类,只是名称不同。我正在尝试确定如何避免为每种对象类型复制 Foreach 循环代码。这可能吗 ?谢谢。

public class TypeA
{
    public string Name { get; set; }
    public string Department { get; set; }
    public string Total { get; set; }
}

public class TypeB
{
    public string Name { get; set; }
    public string Department { get; set; }
    public string Total { get; set; }
}


 private CsvExport GenerateExport<T>(IEnumerable<T> scores)
 {
    CsvExport export = new CsvExport();

    List<TypeA> aList = null;
    List<TypeB> bList = null;

    Type type = scores.GetType();

    if (type.FullName.Contains("TypeA"))
    {
        aList = scores as List<ObjectaModel>;
    }
    else if (type.FullName.Contains("TypeB"))
    {
        bList = scores as List<ObjectbModel>;
    }

    foreach (var dt in aList)
    {
        export.AddRow();
        export["Name"] = dt.Name;
        export["Department"] = dt.Department;
        export["Total "] = dt.Total;
     };

    return export;
}

标签: c#foreach

解决方案


在这种特殊情况下,我强烈建议您将辛勤工作委托给CsvHelper库,您也可以从Nuget获得并像这样使用它......

 public void ExportToCsv<T>(string filename, ImmutableArray<T> objects)
 {
    using (var writer = File.CreateText(filename))
    {
        var csv = new CsvWriter(writer);
        csv.WriteRecords(objects);
    }
  }

对您的问题的更一般的答案是,您必须让两个类都继承自一个公共类或接口,或者您必须使用反射来查找获取命名属性的值。

使用通用接口...

public interface IScore
{
  int HiScore {get;}
}

public class ScrabbleScore : IScore
{
  public int HiScore {get;set;}
}


public class PacManScore : IScore
{
   public int HiScore {get;set;}
}

public void Export<T>(IEnumerable<T> scores) where T: IScore
{
  foreach(var s in scores)
  {
     CvsExport["Hi score"]= s.HiScore;
  }
}

使用反射...

        var CsvExport = new Dictionary<string,string>();
        foreach(var o in scores)
        {   
            //note that checking the type for each object enables you to have heterogenous lists if you want
            var objectType= o.GetType();
            foreach(var p in objectType.GetProperties())
            {
               var propertyName = p.Name;
               CsvExport[propertyName] = p.GetValue(o).ToString();
            }
        }

我会将反射解决方案视为三者中最不受欢迎的解决方案。


推荐阅读