Search code examples
c++-cli

Getting a reference to an element in a List


Is it possible to obtain a reference to an element of a System::Collections::Generic::List when T is a value type?

The following generates warning C4172 because the value returned by the indexer is a temporary copy.

value struct
PluginInfo
{
    //...
};

List<PluginInfo^ pluginInfos = gcnew List<PluginInfo>();

PluginInfo%
GetPluginInfo(Handle handle)
{
    for (i32 i = 0; i < pluginInfos->Count; i++)
    {
        PluginInfo% pluginInfo = pluginInfos[i];
        if (pluginInfo.handle == handle)
        {
            return pluginInfo;
        }
    }
}

Solution

  • No it's not possible.

    The .NET generic collections classes were designed at a time when the main .NET languages (C#, VB.NET) didn't support byref returns. So element access is done exclusively through an (indexed) getter/setter pair, where copies are made.

    This also avoids the drawback of direct element access in sorted collections (e.g. SortedList or Dictionary), which need to know every time an element value changes so that the item can be moved to the correct new location within the collection. In order to maintain a consistent interface, it's not likely that even brand new collections will use byref returns.

    Have you considered using a reference type in your collection? Even if the type you want to store is a value type, you can make a reference class containing it as a member, and that will let you pass it around with reference semantics (at the cost of memory locality, of course).