【问题标题】:C# foreach errorC# foreach 错误
【发布时间】:2011-09-18 18:21:07
【问题描述】:
string connection = "Data Source=" + server + ";Initial Catalog=" + dbase + 
";User ID=" + userid + ";Password=" + password;

conn = new SqlConnection(connection);
conn.Open();
SqlCommand cmd = new SqlCommand("SUBNETTEMP", conn);
cmd.CommandType = CommandType.StoredProcedure;

Parameters d = new Parameters();
d.addparam(15, 1);
d.addparam(15, 2);

foreach (var param in d)
{
    cmd.Parameters.Add(new SqlParameter(param.Key, param.Value));
} 

有一个类叫做参数:

class Parameters
{
    Dictionary<int, int> paramids;
    public Dictionary<int, int> addparam(int sid, int sbid)
    {
        if (paramids == null)
            paramids = new Dictionary<int, int>();
        paramids.Add(sid, sbid);
        return paramids;
    }
}

我不确定为什么会出现错误:“foreach 语句无法对“ConsoleApplication1.Parameters”类型的变量进行操作,因为“ConsoleApplication1.Parameter”不包含 GetEnumerator 的公共定义。

【问题讨论】:

  • 错误信息的哪一部分无法理解?你知道为什么foreach 可以在数组上工作,但不能在例如数组上工作。在DateTime?
  • 我不明白你为什么觉得你需要定义那个类。为什么不直接使用字典呢?或者更好的是,将参数直接添加到命令中?
  • 我同意杰夫的观点。这个类很可能是不必要的。

标签: c#


【解决方案1】:

您的 Parameters 类没有 GetEnumerator 方法。就像错误所说的那样。

您可以遍历 paramids 字段,但为此您需要公开它,这是 IMO 的一个坏主意。

另一种方法是实现GetEnumerator,将其转发给paramids.GetEnumerator

public IEnumerator<KeyValuePair<int,int>> GetEnumerator()
{
    return paramids.GetEnumerator();
}

您还应该添加并实现IEnumerable&lt;KeyValuePair&lt;int,int&gt;&gt;IEnumerable 接口,即使它们对于简单的foreach 来说不是必需的。


附带说明:我认为将内部字典公开为addparam 的返回值是一个可疑的设计选择。如果你想要一个流畅的 API 返回你自己的 Parameters 实例,而不是内部字典。 IE。使用return this

我也将使用 .net 命名约定,因此将您的方法称为 AddParam 而不是 addparam


所以你的完整课程是:

class Parameters:IEnumerable<KeyValuePair<int,int>>
{
    Dictionary<int, int> paramids;

    public Parameters AddParam(int sid, int sbid)
    {
        if (paramids == null)
            paramids = new Dictionary<int, int>();
        paramids.Add(sid, sbid);
        return this;
    }

    public IEnumerator<KeyValuePair<int,int>> GetEnumerator()
    {
        return paramids.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

【讨论】:

  • 我们如何做到这一点..实际上我是 C# 的新手...所以不太了解它。
【解决方案2】:

您的Parameters 类需要继承自Dictionary,或者公开其内部字典以通过foreach 枚举:

class Parameters {
    Dictionary<int, int> paramids;
    ....
    public Dictionary<int, int> ParamIDs {
        get { return paramids; }
    }
}

所以现在这可以工作了:

foreach (var param in d.ParamIDs) {
....
}

【讨论】:

    【解决方案3】:

    如果您想将 Parameters 类用作字典 - 从 Dictionary&lt;int, int&gt; 继承它:

    class Parameters: Dictionary<int, int>
    {
    }
    

    但在这种情况下,最好只使用Dictionary&lt;int, int&gt;

    【讨论】:

      【解决方案4】:

      Parameters 没有GetEnumerator()? 方法,这是foreach 依赖于循环集合的方法。你应该重构 Parameters 类(它看起来有点过度设计,有一个单独的类)并直接使用 Dictionary&lt;&gt;

      另一种方法是让Parameters 实现GetEnumerator()

      class Parameters
      {
          Dictionary<int, int> paramids;
          public Dictionary<int, int> addparam(int sid, int sbid)
          {
              if (paramids == null)
                  paramids = new Dictionary<int, int>();
              paramids.Add(sid, sbid);
              return paramids;
          }
      
          public IEnumerator<KeyValuePair<int, int>> GetEnumerator() 
          { 
              return paramids.GetEnumerator(); 
          }
      }
      

      【讨论】:

      • 不一定需要实现IEnumerable接口,有一个可访问的GetEnumerator()方法返回一个IEnumerator就足够了。
      • @Jeff Mercado:谢谢,不知道。 SO 当然有更多信息:stackoverflow.com/questions/3584351/…
      • 实现IEnumerable&lt;KeyValuePair&lt;int, int&gt;&gt; 仍然是一个好主意。例如,Linq 只有在您实现它时才有效。具有GetEnumerator() 但没有实现IEnumerable&lt;T&gt; 的(非遗留)类对我来说听起来像是一个非常可疑的设计选择。
      猜你喜欢
      • 1970-01-01
      • 2015-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-09
      • 2012-02-07
      • 2012-04-29
      • 2017-07-25
      相关资源
      最近更新 更多