【问题标题】:Generic Extension Method of List<T> does not remove nullsList<T> 的通用扩展方法不会删除空值
【发布时间】:2019-12-17 23:23:52
【问题描述】:

我正在尝试制作一个非常简单的扩展方法,它只是从列表中删除空值。

看起来像这样:

private static List<T> RemoveNulls<T>(this List<T> list) where T : new()
{
    List<T> newList = list.FindAll(x => x != null);
    return newList;
}

真的很简单。我这样称呼它:

foundNeighbors.RemoveNulls();

但有时我仍然返回一个带有空值的列表。这应该是不可能的吧?我是否遗漏了一些关于扩展方法的内容?

【问题讨论】:

  • 看起来你应该这样称呼它:foundNeighbors = foundNeighbors.RemoveNulls();
  • 您能谈谈为什么您向T 添加了一个看似不必要的默认构造函数约束吗?这似乎是一件奇怪的事情。
  • 您能否也谈谈为什么您使用FindAll 来尝试从列表中删除项目而不是RemoveAll?我有兴趣了解人们是如何犯这些错误的,以便我可以设计更好的对象模型。
  • @kuskmen:考虑一个人为的例子:class X { static X x = new X() { P = 1 } public int P { set { Console.WriteLine(X.x == null); } } 我们希望这应该具有X t = new X(); t.P = 1; X.x = t; 的语义,以便设置器观察到X.x 仍然为空。如果这具有X x = new X(); x.P = 1; 的语义,那就太奇怪了,因为现在对X.x 的赋值发生在赋值表达式右侧完成之前,并且这个事实是可以观察到的。
  • @OmniOwl:感谢您的解释。我显然需要使用不可为空的功能。我会尝试你的方案,如果我发现任何相关的东西,我会报告回来。

标签: c# linq extension-methods


【解决方案1】:

您的扩展方法创建并返回一个没有空值的全新列表,它不会改变调用对象。

改为这样使用:

foundNeighbors = foundNeighbors.RemoveNulls();

【讨论】:

  • 我尝试在扩展方法中仅操作列表本身,但无济于事,因此我对其进行了更改。我认为,由于我正在处理this List&lt;T&gt;,它的工作方式与ref 的工作方式相同。他不是这样吗?
  • @OmniOwl Find 方法返回一个新列表,其中仅包含与给定条件匹配的项目子集(在您的情况下不为空)。
  • @hyvte 我的意思是更多,我最初是这样做的:return list.FindAll(x =&gt; x != null); 但仍然没有用。
  • @OmniOwl,这是因为它 (FindAll) 的设计方式是,它将“您的”列表作为参考,然后根据所需的标准制作它的新副本。跨度>
  • 啊,好吧。谢谢@kuskmen
【解决方案2】:

这是一个偏好问题,但我可以建议

public static class ListExt
{
    public static void RemoveNulls<T>(this List<T> list)
        where T : new()
    {
        list.RemoveAll(t => t == null);
    }
}

它不使用任何额外的内存,它只改变 list 实例,从我在问题和 cmets 中看到的这是你想要实现的。

以后你可以随意使用它

foundNeighbors.RemoveNulls();

就像我说的那样,这将直接更改foundNeighbors

@Edit:就像其他人注意到的那样,如果您希望它更快 (O(N)),您应该改用 RemoveAll

【讨论】:

  • 这是O(N ^ 2)的方法,使用list.RemoveAll(i =&gt; i == null)
  • RemoveAt 是 O(N ^ 2) 因为 Array.Copy ?非常感谢朋友,这是一个陷阱
  • @OlivierJacot-Descombes: 不,它是 O(n^2) 因为RemoveAt 在列表的大小上是 O(n) 并且该操作最多完成 O(n) 次,所以我们乘以 ns。
  • 感谢大家的收获,不理解投反对票我从来没有说错什么,但毕竟你能期待什么 :) 不过,今天学到了一些新东西!
猜你喜欢
  • 1970-01-01
  • 2018-01-15
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-22
  • 2012-12-01
  • 1970-01-01
相关资源
最近更新 更多