【问题标题】:What is the C# equivalent to std::vector::iterators?什么是 C# 等价于 std::vector::iterators?
【发布时间】:2013-04-18 12:23:40
【问题描述】:

以下代码 sn-p 显示来自 std::vector C++ 库的 iterator。与此等效的 C# 是什么?考虑到它不是链表,我可以简单地遍历向量中的每个项目吗?迭代器到底在做什么,我如何在 C# 中做同样的事情?完整代码为here

 std::vector<KMeanCluster>::iterator closest_cluster = clusters.begin();

    // Figure out which cluster this color is closest to in RGB space.
    for (std::vector<KMeanCluster>::iterator cluster = clusters.begin();
        cluster != clusters.end(); ++cluster) {
      uint distance_sqr = cluster->GetDistanceSqr(r, g, b);

      if (distance_sqr < distance_sqr_to_closest_cluster) {
        distance_sqr_to_closest_cluster = distance_sqr;
        closest_cluster = cluster;
      }
    }

【问题讨论】:

    标签: c# c++ vector iterator


    【解决方案1】:

    C++ 标准库迭代器的定义方式类似于遍历集合的指针。在 C# 中,每个实现 IEnumerable 的集合都可以在 foreach 循环中进行迭代。除此之外,您仍然可以使用 Enumerators 在 C# 中执行类似于 C++ 迭代器的操作(这在大多数情况下会使事情变得更加困难):

    IEnumerable<int> myCollection = new List<int> { 1, 2, 3 };
    var enumerator = myCollection.GetEnumerator();
    while(enumerator.MoveNext())
        Console.WriteLine(enumerator.Current);
    

    实际上,上面是foreach 循环如何在底层迭代集合。

    foreach(int num in myCollection)
        Console.WriteLine(num);
    

    所以就您的代码而言,这是确切的(但难以编码和理解)等价物:

    IEnumerator<KMeanCluster> closest_cluster = clusters.GetEnumerator();
    while (closest_cluster.MoveNext())
    {
        uint distance_sqr = closest_cluster.Current.GetDistanceSqr(r, g, b);
        if (distance_sqr < distance_sqr_to_closest_cluster)
        {
            distance_sqr_to_closest_cluster = distance_sqr;
            closest_cluster = cluster;
        }
    }
    

    这是最简单的等价物:

    foreach(KMeanCluster closest_cluster in clusters)
    {
        uint distance_sqr = closest_cluster.GetDistanceSqr(r, g, b);
        if (distance_sqr < distance_sqr_to_closest_cluster)
        {
            distance_sqr_to_closest_cluster = distance_sqr;
            closest_cluster = cluster;
        }
    }
    

    【讨论】:

      【解决方案2】:

      迭代器基本上是一个允许串行、非随机访问容器的对象。 无论如何:您可以在 C# 中使用普通循环。 foreach 循环在语法上更接近 C++ 原始语法

      【讨论】:

        【解决方案3】:

        在 C# 中,这可能看起来像:

        var closest_cluster = clusters.FirstOrDefault();
        foreach (var cluster in clusters)
        {
            uint distance_sqr = cluster.GetDistanceSqr(r, g, b);
            if (distance_sqr < distance_sqr_to_closest_cluster)
            {
                distance_sqr_to_closest_cluster = distance_sqr;
                closest_cluster = cluster;
            }
        }
        

        foreach 运算符所做的是它在下面使用IEnumerator,这相当于您的迭代器。

        【讨论】:

        • 如果clusters 不包含任何元素,这将引发异常,这与 C++ 代码不同。 FirstOrDefault() 可能更合适。
        • 当然,在尝试使用closest_cluster之前,您可能仍需要进行空检查
        • @JohnL,是的,但是使用 closest_cluster 的代码超出了当前范围。原代码中也没有这样的检查:screencast.com/t/C7kzJXwwsVi8
        • 是的,但我会认为空列表案例(或空列表案例,就此而言)也在范围之外。
        • @JohnL,我同意。在FirstOrDefault 的情况下,更多的是良好的编码风格问题,这种情况不应该发生。
        【解决方案4】:

        通用集合 - IEnumerator&lt;T&gt;

        支持对泛型集合的简单迭代。

        非泛型集合 - IEnumerator

        支持对非泛型集合的简单迭代。

        这些是接口,应该被继承和覆盖。 MoveNextReset 等方法。然后你可以在循环中使用那个类。

        【讨论】:

          【解决方案5】:

          在 C# 中有一个 iterator 构造,但在这种情况下,您不需要直接访问它,而是使用 foreach 循环。代码可能看起来像这样。

          Cluster closestCluster = clusters.firstOrDefault();
          
          foreach (Cluster currentCluster in clusters)
          {
             //Distance logic
             if (distanceSqr < distanceSqrToClosestCluster)
             {
                  closestCluster = currentCluster;
             }
          }
          

          foreach 在内部通过IEnumerable&lt;Cluster&gt; 接口访问迭代器

          【讨论】:

            猜你喜欢
            • 2012-09-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-09-21
            相关资源
            最近更新 更多