【发布时间】:2018-11-28 10:00:55
【问题描述】:
我有 Select 的 linq,其中创建了 IDisposable 对象。之后有一个过滤器Where,这会导致一些对象永远不会被释放。
这是一个再现:
class Program
{
static void Main(string[] args)
{
var results = "1234567890"
.Select(o => new Test(o))
.Where(o => o.Value > '3' && o.Value < '7')
.ToList();
// do something with results
// ...
// dispose
foreach (var result in results)
result.Dispose();
}
}
class Test : IDisposable
{
public char Value { get; }
public Test(char value)
{
Value = value;
Console.WriteLine($"{Value}");
}
public void Dispose() => Console.WriteLine($"{Value} disposed");
}
输出:
1
2
3
4
5
6
7
8
9
0
4 disposed
5 disposed
6 disposed
问题:
如您所见,有1、2、3、7、8、9、0,它们是被创建但从未被释放的。
我的解决方案:
我可以在Select 中移动Where 条件,但是我需要应用丑陋的“返回null + Where 而不是null”解决方法:
var results = "1234567890".Select(o =>
{
if (o > '3' && o < '7')
return new Test(o);
return null;
}).Where(o => o != null).ToList();
输出:
4
5
6
4 disposed
5 disposed
6 disposed
有没有更好(更优雅)的方式?
如果Select 在某个返回IEnumerable<T> 的库方法中,我的解决方法除了丑陋之外还有一个问题,我无法更改。如何申请Where不漏?
【问题讨论】:
-
如果your comment 为真,则您的解决方案不是有效的解决方法:“不幸的是,在我的情况下,我无法交换 Select 和 Where,因为 Where 使用 Select 返回的对象的属性” 在您的解决方法中,您没有使用这些属性。
-
@Rango,是的,问题的原因。我只是想发布一些解决方案,以防止无所作为。现在我决定在
Where中调用Dispose()作为临时解决方法(感谢Dennis),同时等待/寻找更好的解决方案。 -
该类不应具有检查实例是否相关所必需的
IDisposable属性。相反,它应该具有非一次性财产。该属性应该从外部(构造函数/属性)初始化,或者通过调用使用一次性的方法(例如连接)来初始化。这里太抽象了,但我想你可以将它与模型分开。如果构造函数或方法使用一次性用品,他们有责任将其处置在那里。
标签: c# linq idisposable