Nei*_*ick 49 c# idisposable using yield-return .net-2.0
我已经编写了自己的自定义数据层来保存到特定文件,并使用自定义DataContext模式对其进行抽象.
这完全基于.NET 2.0 Framework(给定目标服务器的约束),所以尽管其中一些可能看起来像LINQ-to-SQL,但它不是!我刚刚实现了类似的数据模式.
请参阅下面的示例,以了解我无法解释的情况示例.
获取Animal的所有实例 - 我这样做,它工作正常
public static IEnumerable<Animal> GetAllAnimals() {
AnimalDataContext dataContext = new AnimalDataContext();
return dataContext.GetAllAnimals();
}
Run Code Online (Sandbox Code Playgroud)
并在下面的AnimalDataContext()中实现GetAllAnimals()方法
public IEnumerable<Animal> GetAllAnimals() {
foreach (var animalName in AnimalXmlReader.GetNames())
{
yield return GetAnimal(animalName);
}
}
Run Code Online (Sandbox Code Playgroud)
AnimalDataContext()实现了IDisposable,因为我在那里有一个XmlTextReader,我想确保它快速清理.
现在,如果我将第一个调用包装在using语句中,就像这样
public static IEnumerable<Animal> GetAllAnimals() {
using(AnimalDataContext dataContext = new AnimalDataContext()) {
return dataContext.GetAllAnimals();
}
}
Run Code Online (Sandbox Code Playgroud)
并在AnimalDataContext.GetAllAnimals()方法的第一行放置一个断点,在AnimalDataContext.Dispose()方法的第一行放置另一个断点,然后执行...
Dispose()方法被称为FIRST,因此AnimalXmlReader.GetNames()给出"对象引用未设置为对象的实例"异常,因为在Dispose()中AnimalXmlReader已设置为null ???
有任何想法吗?我有一种预感,它关系到产生收益没有被允许一个try-catch块,其内部被称为使用有效的代表,编译一次...
SLa*_*aks 57
当你调用GetAllAnimals它时,实际上并不执行任何代码,直到你在foreach循环中枚举返回的IEnumerable.
在枚举IEnumerable之前,一旦包装器方法返回,就会释放dataContext.
最简单的解决方案是使包装器方法也成为迭代器,如下所示:
public static IEnumerable<Animal> GetAllAnimals() {
using (AnimalDataContext dataContext = new AnimalDataContext()) {
foreach (var animalName in dataContext.GetAllAnimals()) {
yield return GetAnimal(animalName);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这样,using语句将在外部迭代器中编译,并且只在外部迭代器被释放时才会被释放.
另一种解决方案是在包装器中枚举IEnumerable.最简单的方法是返回a List<Animal>,如下所示:
public static IEnumerable<Animal> GetAllAnimals() {
using (AnimalDataContext dataContext = new AnimalDataContext()) {
return new List<Animal>(dataContext.GetAllAnimals());
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这会失去延迟执行的好处,因此即使您不需要它们也会获得所有动物.
Guf*_*ffa 11
原因是GetAllAnimals方法不返回动物的集合.它返回一个能够一次返回动物的枚举器.
当您从using块中的GetAllAnimals调用返回结果时,您只需返回枚举器.using块在方法退出之前处理数据上下文,此时枚举器还没有读取任何动物.当您尝试使用枚举器时,它无法从数据上下文中获取任何动物.
解决方法是使GetAllAnimals方法也创建枚举器.这样,在您停止使用该枚举器之前,不会关闭使用块:
public static IEnumerable<Animal> GetAllAnimals() {
using(AnimalDataContext dataContext = new AnimalDataContext()) {
foreach (Animal animal in dataContext.GetAllAnimals()) {
yield return animal;
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14196 次 |
| 最近记录: |