一个使用(){}块中yield return语句执行前作主 [英] yield return statement inside a using() { } block Disposes before executing

查看:158
本文介绍了一个使用(){}块中yield return语句执行前作主的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写我自己的自定义数据层坚持到一个特定的文件,我已经有一个自定义的DataContext图案抽象的。

I've written my own custom data layer to persist to a specific file and I've abstracted it with a custom DataContext pattern.

这是所有基于.NET 2.0框架(目标服务器给定约束),所以尽管它的一些可能看起来像LINQ到SQL,它不是!我刚刚实施了类似的数据模式。

This is all based on the .NET 2.0 Framework (given constraints for the target server), so even though some of it might look like LINQ-to-SQL, its not! I've just implemented a similar data pattern.

请参见下面的例子,我还不能说明情况的例子。

See example below for example of a situation that I cannot yet explain.

要获得动物的所有实例 - 我做到这一点,它工作得很好。

To get all instances of Animal - I do this and it works fine

public static IEnumerable<Animal> GetAllAnimals() {
        AnimalDataContext dataContext = new AnimalDataContext();
            return dataContext.GetAllAnimals();
}

而GetAllAnimals在AnimalDataContext()低于

And the implementation of the GetAllAnimals() method in the AnimalDataContext() below

public IEnumerable<Animal> GetAllAnimals() {
        foreach (var animalName in AnimalXmlReader.GetNames())
        {
            yield return GetAnimal(animalName);
        }
}

该AnimalDataContext()实现IDisposable,因为我有在那里一个XmlTextReader,我想确保它得到迅速清理。

The AnimalDataContext() implements IDisposable because I've got an XmlTextReader in there and I want to make sure it gets cleaned up quickly.

现在,如果我换第一次调用using语句里面像这样

Now if I wrap the first call inside a using statement like so

public static IEnumerable<Animal> GetAllAnimals() {
        using(AnimalDataContext dataContext = new AnimalDataContext()) {
            return dataContext.GetAllAnimals();
        }
}

和把一个断点在AnimalDataContext.GetAllAnimals()方法和在该AnimalDataContext.Dispose()方法中的第一线另一断点的第一行,并执行...

and put a break-point at the first line of the AnimalDataContext.GetAllAnimals() method and another break-point at the first line in the AnimalDataContext.Dispose() method, and execute...

的Dispose()方法,首先是让AnimalXmlReader.GetNames()给出了对象引用未设置为对象实例的异常,因为AnimalXmlReader已经在Dispose()方法???

任何想法?我有一种预感,其相关的收益回报率没有被允许一个try-catch块内被调用,它的使用有效地重新presents,编译一次..

Any ideas? I have a hunch that its related to yield return not being allowed to be called inside a try-catch block, which using effectively represents, once compiled...

推荐答案

当你调用 GetAllAnimals 它实际上并没有,直到你枚举执行任何code返回在IEnumerable的foreach循环。

When you call GetAllAnimals it doesn't actually execute any code until you enumerate the returned IEnumerable in a foreach loop.

在DataContext正在尽快处置的包装方法返回时,你列举了IEnumerable之前。

The dataContext is being disposed as soon as the wrapper method returns, before you enumerate the IEnumerable.

最简单的解决办法是使包装方法的迭代器为好,像这样的:

The simplest solution would be to make the wrapper method an iterator as well, like this:

public static IEnumerable<Animal> GetAllAnimals() {
    using (AnimalDataContext dataContext = new AnimalDataContext()) {
        foreach (var animalName in dataContext.GetAllAnimals()) {
            yield return GetAnimal(animalName);
        }
    }
}

这样的话,使用的语句将在外部迭代器进行编译,外迭代处置时,将只进行处理。

This way, the using statement will be compiled in the outer iterator, and it will only be disposed when the outer iterator is disposed.

另一种解决方案将是列举了IEnumerable在包装。要做到这一点,最简单的方法是返回一个列表与LT;动物&GT; ,就像这样:

Another solution would be to enumerate the IEnumerable in the wrapper. The simplest way to do that would be to return a List<Animal>, like this:

public static IEnumerable<Animal> GetAllAnimals() {
    using (AnimalDataContext dataContext = new AnimalDataContext()) {
        return new List<Animal>(dataContext.GetAllAnimals());
    }
}

请注意,这个失去了延迟执行的好处,因此它会得到所有的动物,即使你不需要他们。

Note that this loses the benefit of deferred execution, so it will get all of the animals even if you don't need them.

这篇关于一个使用(){}块中yield return语句执行前作主的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆