tags:

views:

129

answers:

3

I have an ICollection that I know will only ever have one member. Currently, I loop through it, knowing the loop will only ever run once, to grab the value. Is there a cleaner way to do this?

I could alter the persistentState object to return single values, but that would complicate the rest of the interface. It's grabbing data from XML, and for the most part ICollections are appropriate.

// worldMapLinks ensured to be a singleton
ICollection<IDictionary<string, string>> worldMapLinks = persistentState.GetAllOfType("worldMapLink");

string levelName = ""; //worldMapLinks.GetEnumerator().Current['filePath'];

// this loop will only run once
foreach (IDictionary<string, string> dict in worldMapLinks) // hacky hack hack hack
{
    levelName = dict["filePath"];
}

// proceed with levelName
loadLevel(levelName);

Here is another example of the same issue:

// meta will be a singleton
ICollection<IDictionary<string, string>> meta = persistentState.GetAllOfType("meta");
foreach (IDictionary<string, string> dict in meta) // this loop should only run once. HACKS.
{
    currentLevelName = dict["name"];
    currentLevelCaption = dict["teaserCaption"];
}

Yet another example:

private Vector2 startPositionOfKV(ICollection<IDictionary<string, string>> dicts)
{
    Vector2 result = new Vector2();
    foreach (IDictionary<string, string> dict in dicts) // this loop will only ever run once
    {
        result.X = Single.Parse(dict["x"]);
        result.Y = Single.Parse(dict["y"]);
    }

    return result;
}
+4  A: 

Why not use the Single or FirstOrDefault extension methods?

var levelName = worldMapLinks.Single().Value;

Single has the advantage of enforcing your assumption that there is only 1 value in the enumeration. If this is not true an exception will be raised forcing you to reconsider your logic. FirstOrDefault will return a default value if there is not at least 1 element in the enumeration.

JaredPar
+1 Better answer - `Single` is the best choice here. :)
Andrew Hare
A: 

If you can use LINQ-to-objects in your class, use the Single() extension method on the collection if you know there will be exactly one member. Otherwise, if there could be zero or one, use SingleOrDefault()

Mike Mooney
A: 

Why do you have a collection with only one member? It seems that the real answer should be to better design your system rather than rely on any method to retrieve one element from a collection. You say it makes it more complicated, but how? Isn't this solution itself a complication? Is it possible to change the interface to return one element where applicable and a collection elsewhere? Seems like a code smell to me.

Matt Olenik
This is definitely possible, but using @JaredPar's answer seems better for now.
Rosarch
I agree. It just seems that if there is a case when you KNOW you will be only receiving one element, it is a hint that there's a better semantic option. There may be other cases where large collections are returned, but I think a different method is appropriate for those.
Matt Olenik