scjpike

Bug in ESRI's IEnumBSTR usage (IWorkspaceExtension.DataDictionaryTableNames)

Discussion created by scjpike on Mar 20, 2013
All,

My team has a class very similar to the sample below. It really bothered me when I saw how it signaled that there were no more strings to enumerate (throwing an exception.)

I read the ESRI documentation and it says: "An empty string is returned by Next when there are no more strings to fetch." However, I've tried making the code return string.empty, "", and null, and the same wrong behavior occurs: when ArcMap's code tries to iterate over the the strings, it never detects that the end has been reached. Our workspace extension is returning an instance of the implementation below as the IWorkspaceExtension.DataDictionaryTableNames property value.

My suspicion is that the ESRI code that is using IWorkspaceExtension.DataDictionaryTableNames is relying on the HRESULT rather than the returned value to determine when it has reached the end. I really don't like having to use an exception to control flow--it appears to be working, but it is possible that the fact that it works is a happy accident and we're also introducing instability into the system.

Is this a bug or is there another way to do this without using an exception to control flow?

http://resources.arcgis.com/en/help/arcobjects-net/componenthelp/index.html#//0042000000pp000000
http://resources.arcgis.com/en/help/arcobjects-net/componenthelp/index.html#//002500000m9r000000

public sealed class MyEnumBSTR : IEnumBSTR
{
    private int _index = 0;
    private List<string> _strings = new List<string>();
    private const int S_FALSE = 1;

    public void Add(string strVal)
    {
         _strings.Add(strVal);
    }

    public string Next()
    {
        if (_index < _strings.Count)
        {            
            // return the string at the current index and
            // increment the index
            return _strings[_index++];
        }

        // if we haven't returned a string, we are at the end of the list
        // we should be able to return null, but the ArcObjects API documentation is incorrect
        // a COM exception must be thrown to signal the end of the enumeration
        throw new COMException("Done", S_FALSE);
    }

    public void Reset()
    {
        _index = 0;
    }
}

Outcomes