返回多个对象并对其进行枚举

本文关键字:枚举 对象 返回 | 更新日期: 2023-09-27 18:08:38

我有一个返回WorkInfo对象的方法。它有两个性质:CompanyNameWorkLocation

一个人可能在多家公司工作过。在本例中,我想

  1. 返回WorkInfo对象的数组

  2. WorkInfo对象返回给调用方法后,我需要按以下方式枚举它

    foreach(WorkItem wRow in WorkInfo) 
    {
       string s1 = wRow.CompanyName ;
       string s2 = wRow.WorkLocation;
    }
    

如何在c#中实现这一点?

更新:我所需要做的就是返回相同类型的多个对象的集合,并使用ForEach循环遍历它。

一个数据表返回一个数据表的集合,我们可以使用ForEach(Datarow dr in datatable. rows)来遍历它

同样,我应该做什么来返回一个"WorkInfo"对象的集合,我可以使用ForEach循环?

返回多个对象并对其进行枚举

这是另一个尝试:

注释:快速代码-未经测试-我使用了您的名称约定(如CamelCase)等

public class WorkInfo
{
   public string CompanyName { Get; Set; };
   public string WorkLocation { Get; Set; };
}
public class Example
{
   public List<WorkInfo> GetAList()
   {
      List<WorkInfo> result = new List<WorkInfo>();
      result.Add(new WorkInfo { CompanyName = "MS", WorkLocation = "Redmond" });
      result.Add(new WorkInfo { CompanyName = "Google", WorkLocation = "New York" });
      result.Add(new WorkInfo { CompanyName = "Facebook", WorkLocation = "CA" });
      return result;
   }
   public UseAList()
   {
      foreach(WorkInfo wRow in  GetAList()) 
      {
        string s1 = wRow.CompanyName ;
        string s2 = wRow.WorkLocation;
        // process list elements s1 and s2
      }
   }
}

下面是一些代码,我相信可以解决你的问题:

workInfo = FunctionThatReturnsArray(..);
if (workInfo.Length == 1)
{
   // process single item at workInfo[0]
}
else
{
  foreach(WorkItem wRow in WorkInfo) 
  {
    string s1 = wRow.CompanyName ;
    string s2 = wRow.WorkLocation;
    // process list elements s1 and s2
  }
}

你想要这样的伪代码吗?

public WorkItem[] GetWorkItems(Person p)
{
  WorkItem[] result = YourDatabaseLogicOrBusinessLogic.GetWorkItems(p);
  return result; 
}

然后:

foreach(WorkItem wRow in GetWorkItems(p1)) 
{
   string s1 = wRow.CompanyName ;
   string s2 = wRow.WorkLocation;
}

另一个解决方案,对我来说是最可爱的:),是做这样的东西,伪代码:

 public class WorkInfoEnumerator
    {
        List<WorkItem > wilist= null;
        int currentIndex = -1;

        public MyClassEnumerator(List<WorkItem > list)
        {
            wilist= list;
        }
        public WorkItem Current
        {
            get
            {
                return wilist[currentIndex];
            }
        }
        public bool MoveNext()
        {
            ++currentIndex;
            if (currentIndex < wilist.Count)
                return true;
            return false;
        }   
    }

    public class WorkInfo
    {
        List<WorkItem > mydata = new List<WorkItem >() {.... }; //init here, for example
        public WorkInfoEnumerator GetEnumerator()
        {
            return new WorkInfoEnumerator(mydata);
        }
    }

,在代码的某个地方写正好是你想要的:

     foreach(WorkItem wRow in WorkInfo) 
    {
       string s1 = wRow.CompanyName ;
       string s2 = wRow.WorkLocation;
    }

这样做的美妙之处在于,通过避免明确地实现IEnumerable,您在竞争期间已经具有了强类型控制,因为您实现了自己的枚举器

您想要的设计至少可以说是令人费解的。您可以通过实现一个特别的单链表来实现这一点——在WorkInfo结构中有一个对下一个WorkInfo的引用。然后返回一个WorkInfo,它可能包含也可能不包含对另一个WorkInfo的引用,以此类推。列表中的最后一项具有null。然后在WorkInfo中实现IEnumerable,如果你坚持使用foreach()循环。如果不是,则枚举的形式可能为:

for(;wRow != null; wRow = wRow.Next)    
{
    string s1 = wRow.CompanyName; 
    //...
}

免责声明:如果你做了那件令人讨厌的事,而不是返回一个很好的旧WorkInfo集合,上帝可能会杀死一只小猫。

如果我理解正确,您可以使用linq查询做您正在做的事情。这不是测试,所以不要恨我:)

...Get all workinfos for person and iterate over them,
...grouping by company name.
...Assuming you have an object called workInfos that contains
...the data returned from your datastore.
List<WorkInfo> result = new List<WorkInfo>();
result = (from wi in workInfos
          group wi on wi.CompanyName into gwi
          select new WorkInfo {
              CompanyName = gwi.Key,
              Location = gwi.Location
          }).ToList();

不能100%确定这是否是你正在寻找的,但希望它能帮助,即使只是为了让你思考。

听起来你的困惑是因为你认为你需要两个函数:

public WorkItem GetCompany(User user) { /* ... */ }

public WorkItem[] GetCompanies(User user) { /* ... */ }

但是你不需要两者都需要。你可以只写一个函数来处理这两种情况。

基本上,foreach接受IEnumerable(例如数组,列表,Linq查询的结果),并循环它。

IEnumerable可以枚举0、1或多个对象。你可以把它想象成包含这么多对象的枚举。对于列表或数组,这很有意义。

为了支持只返回单个公司,您可以只返回大小为1的IEnumerable(列表或数组)。

public WorkItem[] GetCompanies(User user)
{
    // Todo: some DB query here
    // if we get 5 results, return them as an array of size 5
    // If we get one result, return it as an array of size 1
}

如果您需要代码处理函数只返回单个结果的特殊情况,则只需检查.Count.Length成员。

WorkItem[] result = GetCompanies(user);
if(result.Length == 0)
{
    // todo: is this an error?  If so, let the user know here
}
else if(result.Length == 1)
{
    WorkItem theOnlyCompany = result[0];
    // todo: do something interesting here, for the 1-company case
}
else
{
    foreach(WorkItem in result)
    {
        // todo: do something interesting here, for the multi-company case
    }
}

但是,除非您真的需要对单个公司/多个公司进行区别对待,否则我建议您完全取消长度检查,只编写一组代码。

其他人已经表明,您可以让您的函数返回一个数组或列表并对其进行foreach。如果只有一个条目,它也会工作得很好。

如果您必须一次检索一个,您也可以自己实现枚举逻辑:

public IEnumerable<WorkItem> WorkItems(Person p)
{
    WorkItem item = GetAWorkItem(p);
    yield result item;
}

:

foreach(WorkItem item in WorkItems()) 
{
   string s1 = item.CompanyName;
   string s2 = item.WorkLocation;
}

我是这样做的。

public Tuple<int, int> ReturnMultipleValues()
{
     return new Tuple<int,int>(1,2);
}