最近有一个bug困扰了很久,找了半天终于发现了,现在做个总结,方便以后查阅。
在开发过程中,有一个问题就是IFeatureClass.Search()方法,这个方法中有两个参数。
public IFeatureCursor Search (
IQueryFilter filter,
bool Recycling
);
第一个参数是查询条件,不多介绍,第二个参数是是否进行垃圾回收,对于这个参数的设置,有很多的学问。网上的查询教程一般都是设置为false。但是也有人提出设置为true的话会更快一些,在arcengine的开发帮助文档中也有提到。
The recycling parameter controls row object allocation behavior. Recycling cursors rehydrate a single feature object on each fetch and can be used to optimize read-only access, for example, when drawing. It is illegal to maintain a reference on a feature object returned by a recycling cursor across multiple calls to NextFeature on the cursor. Features returned by a recycling cursor should not be modified. Non-recycling cursors return a separate feature object on each fetch. The features returned by a non-recycling cursor may be modified and stored with polymorphic behavior.
可以看出,如果设置为true的话,每次IFeatureCursor.NextFeature()所拿到的IFeature就是同一个值,而false则是每次拿到的是其副本。这点很像值和引用之前的关系。下面给出例子。
/// <summary>
/// 按行来比较
/// </summary>
/// <returns></returns>
public IList<DiffRowWith2Dic> GetDiffFeatrRowFirst()
{
IList<DiffRowWith2Dic> diffRowList = new List<DiffRowWith2Dic>();
IFeatureCursor baseFeatrCursor = _baseFeatrCls.Search(null, false);
//IFeatureCursor baseFeatrCursor = _baseFeatrCls.Search(null, true);
IFeature baseFeatr = baseFeatrCursor.NextFeature();
while (baseFeatr != null)
{
QueryConstructor queryConstrutor = new QueryConstructor();
IQueryFilter queryFilter = queryConstrutor.CreateQueryFilter(baseFeatr);
IFeatureCursor toCmprFeatrCursor = _toCmprFeatrCls.Search(queryFilter, false);
IFeature toComprFeatr = toCmprFeatrCursor.NextFeature();
System.Runtime.InteropServices.Marshal.ReleaseComObject(toCmprFeatrCursor);
if (toComprFeatr == null)
{
baseFeatr = baseFeatrCursor.NextFeature();
continue;
}
foreach (string cmprFld in _cmprFldsList)
{
if (!IsAttributeSame(baseFeatr, toComprFeatr, cmprFld))
{
DiffRowWith2Dic primeDiffRow = new DiffRowWith2Dic();
primeDiffRow.baseFeatr = baseFeatr;
primeDiffRow.baseStr = GetDataSetPath(_baseFeatrCls.FeatureDataset.Workspace.PathName);
primeDiffRow.toCmprFeatr = toComprFeatr;
primeDiffRow.toCmprStr = GetDataSetPath(_toCmprFeatrCls.FeatureDataset.Workspace.PathName);
diffRowList.Add(primeDiffRow);
break;
}
}
baseFeatr = baseFeatrCursor.NextFeature();
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(baseFeatrCursor);
//GC.Collect();
return diffRowList;
}
/// <summary>
/// 存储比较结果
/// </summary>
public struct DiffRowWith2Dic
{
public IFeature baseFeatr;
public string baseStr;
public IFeature toCmprFeatr;
public string toCmprStr;
}
在一开始,我的baseFeatrCursor是通过_baseFeatrCls.Search(null, true)来拿到的,然后发现每次我diffRowList中的baseFeatr都是一样的,其结果都是通过baseFeatrCursor.NextFeature()拿到的最新的baseFeatr,这个结果就很像是我拿到的只是baseFeatr的一个指针,而不是其中的对象。而toCmprFeatr不会出现上述问题,因为每次的toCmprFeatrCursor都是toCmprFeatrCls新Search()出来的结果,每次只用一次。
把_baseFeatrCls.Search(null, true)该为_baseFeatrCls.Search(null, false)问题就解决了。