【问题标题】:Adding element to IEnumerable<IPublishedContent>将元素添加到 IEnumerable<IPublishedContent>
【发布时间】:2017-02-13 11:30:55
【问题描述】:

我有两个 IEnumerable 对象,如果满足特定条件,我需要将每个元素从第一个 IEnumerable 带到第二个 IEnumerable。我的代码是这样的

IEnumerable<IPublishedContent> nodesTemp = posts.Take(10).ToList();
IEnumerable<IPublishedContent> nodes = null;
foreach (var n in nodesTemp)
{
    if (condition=true)
    {
        nodes.add(n);           
    }
}

但这会引发错误

:“System.Collections.Generic.IEnumerable”不包含“add”的定义,也没有接受“System.Collections.Generic”类型的第一个参数的扩展方法“add” .IEnumerable' 可以找到(您是否缺少 using 指令或程序集引用?)

完整代码供参考

 IEnumerable<IPublishedContent> nodesTemp = posts.Take(count).ToList();

IEnumerable<IPublishedContent> nodes = null;
foreach (IPublishedContent n in nodesTemp)
{
    var rolename = n.GetProperty("focusedUserGroup").Value.ToString();
    var username = umbraco.cms.businesslogic.member.Member.GetCurrentMember().Text;
    var flag = false;

    if (!string.IsNullOrEmpty(rolename))
    {
        var groups = rolename.Split(',');

        foreach (var group in groups)
        {
            if (Roles.IsUserInRole(username, group))
            {
                nodes.add(n);
                break;
            }
        }

    }
}

【问题讨论】:

  • 你不能添加IEnumerable它是只读的。采取List
  • @Div 你能建议任何解决方法,以便我可以将一些特定项目从一个 IEnumerable 转移到另一个?
  • 可以是几千行代码。但你总是可以把它放在功能上。然后在查询中使用它。
  • 没有区别 - 您可以将谓词重构为任意数量的函数。最终,所有“条件”都需要是Func&lt;IPublishedContent, bool&gt;
  • Div 的评论可能是对的。如果在循环之前将nodes 声明为var nodes = new List&lt;IPublishedContent&gt;(); 而不是= null,则可以将.Add(大写A)声明为List&lt;&gt;。这样的List&lt;&gt; 实现了IEnumerable&lt;&gt;(而后者的接口甚至是协变的)。

标签: c# asp.net linq generics


【解决方案1】:

你不能这样做。原因是因为 IEnumerable 只是代表某个集合的迭代器。它可以是内存中的数组,也可以是从远程数据库中选择,甚至是这样的常量调用:

IEnumerable<int> GetSomeConsts()
{
    yield return 1;
    yield return 101;
    yield return 22;
}

您可以做的是扩展您的第一个集合的后迭代器。比如这样:

bool IsCondition(IPublishedContent n)
{
    var rolename = n.GetProperty("focusedUserGroup").Value.ToString();
    var username = umbraco.cms.businesslogic.member.Member.GetCurrentMember().Text;

    if (!string.IsNullOrEmpty(rolename))
    {
        var groups = rolename.Split(',');

        foreach (var group in groups)
        {
            if (Roles.IsUserInRole(username, group))
            {
                 return true;
            }
        }
    }
    return false;
}

那就这样称呼它吧:

var nodes = posts.Take(count).Where(IsCondition);

【讨论】:

  • 您能否建议任何解决方法,以便我可以将一些特定项目从一个 IEnumerable 转移到另一个?
  • 事实上,你应该也可以将最后的for循环缩写成return groups.Any(grp =&gt; Roles.IsUserInRole(username, grp));
【解决方案2】:

我认为这是一个很好的例子,说明您可以使用 yield return 来实现

例如:

public IEnumerable<IPublishedContent> Whatever(IEnmerable<IPublishedContent> nodes, int count)
{
    foreach(var node in nodes.Take(count))
    {
        var rolename = node.GetProperty("focusedUserGroup").Value.ToString();
        var username = umbraco.cms.businesslogic.member.Member.GetCurrentMember().Text;
        if (!string.IsNullOrEmpty(rolename))
        {
            var groups = rolename.Split(',');

            foreach (var group in groups)
            {
                if (Roles.IsUserInRole(username, group))
                {
                     yield return node; //yield return allows you to create a new enumerable inline
                     break;
                }
            }
        }
    }
}

yield return 将在您枚举代码时执行您的代码,因此如果您要调用 What(...).First(),它只会运行代码,直到找到第一个 yield return。

【讨论】:

    【解决方案3】:

    看起来您正在过滤一个 IEnumerable。

    这种情况下,你不需要先把它变成一个列表,你可以使用Enumerable&lt;T&gt;.Where()来过滤它。

    这样的事情应该可以工作:

    var nodesTemp = posts.Take(10);
    var nodes = nodesTemp.Where(item => predicate(item));
    

    其中predicate(item) 是某个函数,它接受IPublishedContent 类型的参数并返回bool

    您可以将其写为 lambda 表达式,例如:

    var nodesTemp = posts.Take(10);
    var nodes = nodesTemp.Where(item => item.SomeProperty == someTargetValue);
    

    如果您需要nodes 成为列表而不是IEnumerable&lt;IPublishedContent&gt;,则可以将其转换为列表:

    var nodes = nodesTemp.Where(item => item.SomeProperty == someTargetValue).ToList();
    

    此时您可能并不真正需要nodesTemp(除非您将其用于调试目的):

    var nodes = 
        posts.Take(10)
        .Where(item => item.SomeProperty == someTargetValue)
        .ToList();
    

    【讨论】:

      猜你喜欢
      • 2013-06-18
      • 2011-03-24
      • 1970-01-01
      • 2011-06-28
      • 1970-01-01
      • 2013-08-22
      • 2013-01-23
      • 2019-10-14
      • 2021-03-19
      相关资源
      最近更新 更多