2014-01-30 43 views
-2

您好我想创建一个foreach与2语句这样的foreach与2语句

foreach (CSheet mySheet in mySheets && CSheet nameQuiz in nameQuizs) { 
    //problem if i just used one statement in foreach i can't give property 'name' to 
      nameQuiz...so it's limited like this 
    oSheet = mySheet.name.toString(); 

    //i wanna make nameQuiz have property name too like mysheet 
    oSheet = mySheet.name.toString(); 
    oName = nameQuiz.name.toString(); 
} 

这是我CSheets

public class CSheet 
{ 
    public string name; 
    public CCell[] cells; 
} 

mysheets & nameQuizs是阵列
什么想法?


阿图尔

public static string exportToExcel(string fileName, CSheet[] mySheets, CSheet[] nameQuizs) 

基于代码mySheets & nameQUizs相关或不?我怎么知道他们是否相关?

+2

你能解释一下你的循环会做什么吗? –

+0

@katik在你的“artur”上编辑:Erm ... if *你*不知道'mySheets'和'nameQuizs'是如何相关的,谁知道? *你是编写代码的人,那么你的意图是什么?他们在某些方面有关系吗?你为什么想同时循环两者?代码背后的逻辑是什么? –

+0

实际上这个项目不是我从零创建的......我只是修复了任何bug,所以我几乎不能很好地理解这段代码的一部分,这是第一个项目C#我处理,所以我仍然在学习......为你的第二个问题,因为如果我创建不同的循环...结果真的不同,我想 – Neversaysblack

回答

3

你不能这样做。你可以用一个for循环做到这一点,但是:

for (int i = 0; i < Math.Min(mySheets.Count, nameQuizs.Count); i++) 
{ 
    CSheet mySheet = i < mySheets.Count ? mySheets[i] : null; 
    CSheet nameQuiz = i < nameQuizs.Count ? nameQuizs[i] : null; 

    oSheet = mySheet != null ? mySheet.name : String.Empty; 
    oName = nameQuiz != null ? nameQuiz.name : String.Empty; 
} 

在ACSE您mySheetsnameQuizs名单其实都是数组,你需要Length更换Count

此外,您不需要name.ToString();,因为name成员已经是String

+0

从理论上说,'mySheets'或'nameQuizs'可以是任何种类IEnumerable'的'那里得到一个“计数”(或“长度”)可能很困难。 – Corak

+0

一方面,这是真的,另一方面,我们只希望最好的:-)我只是在提出一个建议。 –

+0

我得到错误错误'操作符'<'不能应用于类型'int'和'方法组'的操作数' – Neversaysblack

4

您可以zip两个序列(即采取从两个序列的相应项):

foreach (var item in mySheets.Zip(nameQuizs, (s,nq) => new { mySheet = s, nameQuiz = nq })) 
{ 
    oSheet = item.mySheet.name;  
    oSheet = item.mySheet.name; 
    oName = item.nameQuiz.name;  
} 

UPDATE:因此您使用.NET 3.5 zip扩展不可用。但是你可以写你自己:

public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(
    this IEnumerable<TFirst> firstSource, 
    IEnumerable<TSecond> secondSource, 
    Func<TFirst, TSecond, TResult> selector) 
{ 
    using(var firstIterator = firstSource.GetEnumerator()) 
    using(var secondIterator = secondSource.GetEnumerator()) 
    { 
     while(firstIterator.MoveNext() && secondIterator.MoveNext()) 
      yield return selector(firstIterator.Current, secondIterator.Current); 
    } 
} 
+2

+1该死,再次太迟了。 –

+0

我得到的错误'systemArray不包含zip的定义'sory忘记写mySheets&nameQuizs是 – Neversaysblack

+0

@katik添加'System.Linq'命名空间使用到您的代码文件之前的数组。 Zip是在该命名空间中定义的扩展方法 –

1

如果你想通过循环元素的同时从两个存在使用:

var mySheetsEnum = mySheets.GetEnumerator(); 
var nameQuizsEnum = nameQuizs .GetEnumerator(); 

while(mySheetsEnum.MoveNext() && nameQuizsEnum.MoveNext()) 
{ 
    ... 
} 

;否则可以使用||代替&&

+0

顺便说一句,这正是在ZipIterator中发生的:)另外它更好地将枚举器包装成使用语句 –

+0

@SergeyBerezovskiy完全同意。 –

1

您可以通过使用Zip extension method得到这个成一个圈相当漂亮:

foreach (var item in mySheets.Zip(nameQuizs, (s, q) => Tuple.Create(s, q))) 
{ 
    var mySheet = item.Item1; 
    var nameQuiz = item.Item2; 
} 

取而代之的是Tuple,匿名类型也许是一个更好的解决方案。见Sergey's answer

它的功能基本上是迭代到序列并将每个集合的下一个元素相互压缩。通常你会以某种方式合并它们,或者将它们复制到Tuple或任何自定义对象中。

尽管隐喻并不完美,但您可能会想到将两条高速公路车道合并为一条,其中应用了zip-merge概念。然而,在这里我们得到了一对车,而不是一条长长的线。

+0

来自元组的属性看起来比匿名类型的命名属性更优雅吗? –

+1

@SergeyBerezovskiy不,我认为你的解决方案更好。看到我的帖子后立即看到你的回答。 –

+0

确定:)这是我个人不喜欢的C#元组 –

2

如果mySheets和nameQuizs是相关的,你可以把它们放在一起字典中,并且列举它。

或者使用for循环和每个元素的索引。

+0

请检查我编辑的帖子 – Neversaysblack