3

I wanted to know how to apply a constructor on each element of an array that would then return an array of constructed objects. Specifically, I am working with C#'s TreeNode. The concept I want is as follows:

string[] animals = {"dog","cat","mouse"};
TreeNode[] animalNodes = TreeNode[](animals);

Where TreeNode[](animals) would have the cumulative effect of

animalNodes[0] = TreeNode("dog");
animalNodes[1] = TreeNode("cat");
animalNodes[2] = TreeNode("mouse");

I know I can us foreach and load such a structure manually but if possible, I'm looking for the elegant 'one line' way. I have looked long and hard for how to do this but could not find anything.

3 Answers 3

7

Some LINQ will do the trick:

TreeNode[] animalNodes = animals.Select(a => new TreeNode(a)).ToArray();

The Select extension method executes the specified delegate (specified via a lambda here) on each member of the list, and creates a list of the results (IEnumerable<TreeNode> in this case). The ToArray extension method is then used to create an array from the result.

Alternatively, you can use LINQ's query syntax:

TreeNode[] animalNodes = (from a in animals select new TreeNode(a)).ToArray();

The code generated by the compiler is the same for both these examples.

Sign up to request clarification or add additional context in comments.

1 Comment

A year out follow up: I love LINQ. I use it every chance I get. Thanks for introducing me to this syntactic sugary delight.
0

This is a different syntax that will give the same result like the other correct answer you already got.

TreeNode[] animalNodes = (from animal in animals select new TreeNode(animal)).ToArray();

1 Comment

I added that to my answer about a minute before you posted this. ;)
0

While the other answers may work, I propose the following alternative.

My main reason for doing so is that the other examples require you to actually make the code look a little bit more complicated, and it's clear that you're looking to clean up your code, and make the assignment look and be more simple. This solution will also help you if you're going to be creating these TreeNodes in different places in your app (the other solutions would require you to copy and paste the assignment code to each place you're creating the TreeNode arrays.

The cost of having your assignment code cleaner, is moving the mess somewhere else (but honestly not really much of a mess, since it's all really straight-forward)

First, create a class to build the TreeNode array for you

public static class TreeNodeBuilder
{
    public static TreeNode[] FromStringArray(String[] array)
    {
        TreeNode[] returnValue = new TreeNode[array.Length];

        for(int i = 0; i < array.Length; i++)
        {
            returnValue[i] = new TreeNode(array[i]);
        }

        return returnValue;
    }
}

And then in your assignment code, you can use the following:

String[] animals = {"dog", "cat", "mouse"};
TreeNode[] animalNodes = TreeNodeBuilder.FromStringArray(animals);

Conclusion

This (IMHO) is a better option than using LINQ as the other answers provide, mostly for code clarity, maintainability, and the separation you can achieve by putting all of this logic in a different file (a file like TreeNodeBuilder.cs).

For what it is worth you could also use the LINQ code provided in the other answers inside the above FromStringArray function (if you wanted to get the best of both worlds).

Anyways, my two cents :) Hope you find it helpful.

3 Comments

I think this is much less maintainable than the LINQ solution, because you need to create one method for each type you want to create. And it's also less clear, because “everyone” knows what Select() does, but it's not immediately clear what your method does.
Also, you could use the same argument for any piece of code that uses LINQ. Are you suggesting not to use LINQ at all?
A) Take a look at the constructors for the TreeNode class: msdn.microsoft.com/en-us/library/…, I think it becomes clear that there is not a need for implementing other types. And if there was that need, you would need to implement different LINQ to handle those cases as well. B) Not at all am I suggesting not to use LINQ at all. LINQ is powerful, and generally kicks ass. But specifically to make code look a bit cleaner in such a small case as this, I think it's not unreasonable to use something other than LINQ. Performance will be identical.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.