【问题标题】:foreach statement cannot operate on variables of type 'object' [duplicate]foreach 语句不能对“object”类型的变量进行操作 [重复]
【发布时间】:2015-02-10 05:20:37
【问题描述】:

我有 3 个下拉列表 2 具有相同的来源,第 3 个具有选定列表。如果选择的列表不为空,我应该从第一个中删除选择,并在第三个中绑定。第二个是显示原始列表的静态。

但我不知道如何在对象中进行 foreach。

错误:foreach 语句不能对“object”类型的变量进行操作 因为“对象”不包含公共定义 'GetEnumerator'

    public void DataSource(object source, object select, string Value = "UId", string Text = "Text")
    {
        ddlThis.DataSource = source;
        ddlThis.DataTextField = Text;
        ddlThis.DataValueField = Value;
        ddlThis.DataBind();

        ddlThisHidden.DataSource = source;
        ddlThisHidden.DataTextField = Text;
        ddlThisHidden.DataValueField = Value;
        ddlThisHidden.DataBind();

        if (select != null)
        {
            ddlOther.DataSource = select;
            ddlOther.DataTextField = Text;
            ddlOther.DataValueField = Value;
            ddlOther.DataBind();

            foreach (var item in ddlOther.DataSource)
                ddlThis.Items.Remove(item);
        }
    }

第 2 版

    public void DataSource(IList source, IList select, string Value = "UId", string Text = "Text")
    {
        ddlThis.DataSource = source;
        ddlThis.DataTextField = Text;
        ddlThis.DataValueField = Value;
        ddlThis.DataBind();

        ddlThisHidden.DataSource = source;
        ddlThisHidden.DataTextField = Text;
        ddlThisHidden.DataValueField = Value;
        ddlThisHidden.DataBind();

        if (select != null)
        {
            ddlOther.DataSource = source.Cast<object>()
                .Select(x => select.Cast<object>().Any(c=> c.GetType().GetProperty(Value).GetValue(source, null).ToString() == x.GetType().GetProperty(Value).GetValue(source, null).ToString()));
            ddlOther.DataTextField = Text;
            ddlOther.DataValueField = Value;
            ddlOther.DataBind();

            foreach (var item in select)
                ddlThis.Items.Remove(item.ToString());
        }
    }

版本 3 工作!

    public void DataSource(object source, object select, string Value = "UId", string Text = "Text")
    {
        ddlThis.DataSource = source;
        ddlThis.DataTextField = Text;
        ddlThis.DataValueField = Value;
        ddlThis.DataBind();

        ddlThisHidden.DataSource = source;
        ddlThisHidden.DataTextField = Text;
        ddlThisHidden.DataValueField = Value;
        ddlThisHidden.DataBind();

        if (select != null)
        {
            ddlOther.DataSource = ((IEnumerable)source).Cast<dynamic>().ToList().FindAll(x => ((IEnumerable)select).Cast<dynamic>()
                .Any(c => c.GetType().GetProperty(Value).GetValue(c, null) == x.GetType().GetProperty(Value).GetValue(x, null)));

            ddlOther.DataTextField = Text;
            ddlOther.DataValueField = Value;
            ddlOther.DataBind();

            foreach (var item in (dynamic)(ddlOther.DataSource))
                ddlThis.Items.Remove(item.ToString());
        }
    }

【问题讨论】:

  • 你不能。对象本身(比 System.Object 更派生的类型)必须实现 IEnumerable 才能通过它。 ddlOther.DataSource 对我来说似乎是 system.object 类型。为什么“源”是对象?这就是问题所在。
  • DataSource 是一个object,我想你想遍历ddlOther.Items
  • 我很想知道您为什么将传递的值声明为对象而不是特定的 IList 对象
  • 好的,我正在将对象更改为 IList,我想应该可以。
  • 我改为 IList,但现在得到“对象与目标类型不匹配”。在“ddlOther.DataSource”中

标签: c# linq foreach


【解决方案1】:

如果您不知道对象的确切类型,但您确定无论它是什么,它上面都会有GetEnumerator(比如说,因为它是一个集合或您自己的对象之一,它实现了IEnumerable ) 你可以通过转换为dynamic 来阻止编译器发出错误,如下所示:

foreach (var item in (dynamic)(ddlOther.DataSource)) {
    ...
}

这里的权衡是,如果事实证明 ddlOther.DataSource 没有 GetEnumerator,您将在运行时收到错误,而不是编译时错误。

【讨论】:

  • 是的动态解决了我的问题!只是我有最后一个小问题 ddlOther.DataSource = ((IEnumerable)source).Cast().ToList().FindAll(x => ((IEnumerable)select).Cast().Any(c => c.UId == x.UId));在这段代码中,我手动给出了“UId”,但我想动态地给出属性名称,我可以这样做吗?像 .Any(c => c[Value] == x[Value]));
  • 您可以在版本 3 中签入问题。更易于阅读。
  • @Mert 不幸的是,仅使用dynamic 无法将属性名称作为字符串传递。您需要创建一个通过反射或通过 Linq.Expressions 的方法来做到这一点。
  • 是的,我只是通过反射完成的!非常感谢
【解决方案2】:

修改您的代码以检查 IEnumerable 接口。它有一种感觉,潜在的修正是你想要的。

public void DataSource(object source, object select, string Value = "UId", string Text = "Text")
{
    ddlThis.DataSource = source;
    ddlThis.DataTextField = Text;
    ddlThis.DataValueField = Value;
    ddlThis.DataBind();

    ddlThisHidden.DataSource = source;
    ddlThisHidden.DataTextField = Text;
    ddlThisHidden.DataValueField = Value;
    ddlThisHidden.DataBind();

    if (select != null)
    {
        ddlOther.DataSource = select;
        ddlOther.DataTextField = Text;
        ddlOther.DataValueField = Value;
        ddlOther.DataBind();

        if (select is IEnumerable) //check if the object is a list of objects
            foreach (var item in (IEnumerable)ddlOther.DataSource)
                ddlThis.Items.Remove(item);
        else //try to remove the single object
            ddlThis.Items.Remove(select)
    }
}

【讨论】:

  • 这不会修复编译错误,因为在object 上尝试foreach 的代码仍然存在。
  • 忘记演员表...对不起...已编辑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多