我的问题需要 3 个(不是太长的函数)来重现(VS2010/.NET 4)
在第一种情况下,我的 IEnumerable 未被评估(通过 ToList() 方法)
我不明白为什么..
//主程序
private void ButtonTest_Click(object sender, RoutedEventArgs args)
{
int[] indexes = new int[] { 2, 2, 2, 2, 2, 2 };
var query = Odometer(indexes);
// 1) Iterator not evaluated ???
var temp = query.ToList();
MessageBox.Show(AsString(temp[3]));
// 2) OK in this case
int count = 0;
foreach (int[] item in query)
{
count++;
if (count == 3)
MessageBox.Show(AsString(item));
}
}
/// <summary>
/// Generate all tuples between 0 and indexes[i]-1
/// Ex :
/// Odometer(new int[]{2, 3}); // (0, 0) (0, 1) (0, 2) (1, 0) (1, 1) (1, 2)
/// </summary>
/// <param name="indexes"></param>
/// <returns></returns>
public static IEnumerable<int[]> Odometer(int[] indexes)
{
int[] result = new int[indexes.Length];
for (int i = 0; i < indexes.Length; i++)
result[i] = -1;
int ptr = 0;
while (ptr >= 0)
{
while (ptr < indexes.Length)
{
result[ptr++]++;
continue;
}
ptr--;
while (result[ptr] < indexes[ptr])
{
yield return result;
result[ptr]++;
}
result[ptr]--;
while (result[ptr] == indexes[ptr] - 1)
{
result[ptr] = -1;
ptr--;
if (ptr < 0)
break;
}
}
}
/// <summary>
/// Format an IList of T
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="array"></param>
/// <returns></returns>
private static string AsString<T>(IList<T> array)
{
StringBuilder builder = new StringBuilder();
foreach (T item in array)
builder.AppendFormat("{0}, ", item);
if (builder.Length >= 2)
builder.Length -= 2;
return builder.ToString();
}
在此先感谢您的帮助
菲利普
您的 IEnumerable 在以下情况下运行:
var temp = query.ToList();
我在 Odometer 中创建了一个断点,果然它坏了。它包含很多-1 的列表。也许您需要更好的里程计方法?
编辑: 问题是您总是返回同一个数组。因此它将始终具有相同的值。您应该阅读一些有关 .Net/C# 中的引用的内容。此外,该方法只需要长度,因此只需发送长度。
public static IEnumerable<int[]> Odometer(int[] indexes)
{
int[] result = new int[indexes.Length];
for (int i = 0; i < indexes.Length; i++)
result[i] = -1;
int ptr = 0;
while (ptr >= 0)
{
while (ptr < indexes.Length)
{
result[ptr++]++;
continue;
}
ptr--;
while (result[ptr] < indexes[ptr])
{
//HERE
//Clones the array so you are returning a new array - thanks Jon, for improvement on the Array.Copy code.
yield return result.ToArray();
result[ptr]++;
}
result[ptr]--;
while (result[ptr] == indexes[ptr] - 1)
{
result[ptr] = -1;
ptr--;
if (ptr < 0)
break;
}
}
}
我是一名优秀的程序员,十分优秀!