Generalizing constructors to operate on arrays in C# - c#

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.

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.

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();

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.

Related

Legacy collection querying before LINQ

I'm looking to give a talk about LINQ, and wanted to mention how querying collections used to work. Back in .Net 1.1, I seem to remember there being a method (Find() maybe?) where you would pass the address of another method which would interrogate each item in the collection and determine whether it should be included in the filtered collection.
Am I completely misremembering this? It stuck with me, as the syntax was unusual for the time.
I thought it was something like:
public bool ContainsFoo(string term){
if(term.contains("Foo"){
return true;
}
return false;
}
And you could call it like:
filteredCollection = collection.Find(ContainsFoo);
I seem to remember a lot of people commenting on how LINQ was so much faster to code because developers could now write functions in-line. How were we writing functions "out-line" previously?
Before LINQ you were just limited to all the built-in List/List<T> methods, and yes Find is one of them (still is). The difference is it expects a Predicate<T> as opposed to a Func<Boolean, T> which you can still do inline e.g.
var found = list.Find(delegate(Item item) { return item != null; });
Or as you demonstrated by using a named method.

Removing from list recursively in C#

I have the following recursive function that is used to search down a hierarchical tree and remove found objects from a list:
private List<Tag> RemoveInvalidTags(Device device, List<Tag> tags)
{
var childDevices = device.ChildDevices.Select(c => c.ChildDevice);
foreach (var child in childDevices)
{
tags.Remove(child.Tag);
RemoveInvalidTags(child, tags);
}
return tags;
}
What I am expecting this to do is remove all child device tags at this level from the tags list, call the function recursively for your children, then return that list up to the previous level.
Will this pass the tags list by reference and modify the original passed list? Or should I be doing something along the lines of
validTags = CollectValidTags(child, tags);
and adding up all the returned lists?
Will this pass the tags list by reference
No. The list object is passed "by value" (but see next). (ref or out is required to "pass by reference" in C#, but that is not being done here, nor does it need to be.)
and modify the original passed list?
Yes. This is because the list object is passed. And that list object is mutated. Passing a reference type (anything defined with class) never implicitly makes a copy/clone/duplicate. An object is what it is.
Now, back to "pass by value": the "value passed" is the value of the "reference" (internal, no need to concern with this): this calling strategy is better known as Call/Pass By Object Sharing in a langauge like C#. The same object is shared (just as if it were assigned to two different variables). (Value types -- a struct -- are different in that they (often) are copied/duplicated on the stack, but a List<T> is a class.)
Or should I be doing something along the lines of
It depends upon the desired semantics. Is the caller expecting the side-effects directly or indirectly? Can the mutation side-effect lead to unexpected scenarios? Make sure to document it either way. (I prefer the way that guarantees the initial object is not mutated.)
Hope that clears some things up.
Happy coding.
In your code you are modifying the items in your tags parameter and passing back the modified list as your result. You want to avoid modifying lists in this way - especially inside loops where it can cause you grief in many situations.
I have a LINQ-based alternative for you.
If I understand the intent of your code you want to do something like this:
Func<Device, IEnumerable<Device>> flatten = null;
flatten = d =>
{
return (new [] { d }).Concat(
from c in d.ChildDevices
from f in flatten(c)
select f);
};
var collectedValidTags = flatten(device).Select(d => d.Tag);
var result = tags.Except(collectedValidTags).ToList();
This approach doesn't pass your list of tags around so there is no chance of modifying your original list.
Does this help?
Short answer - your code will do what you want.
Long answer - you should read descriptions of what the ref keyword does. I would suggest you read as many descriptions as possible; there are many different ways to articulate it ("I like to think of it as... ") and some will work for you whilst others won't. If you read many descriptions (from people who understand it) then some kind of understanding should gel for you.
Here's a list to get you started:
Use of 'ref' keyword in C# (my answer)
C# ref keyword usage
Passing by ref?
Example of practical of "ref" use

How can I create a sequence of numbered variables at run time?

Friends, I must create a series of ArrayLists, each containing objects of unknown origin, with each instance assigned to a separate local variable.
So far, so good... But I also need each local variable's name to follow a very specific pattern: the name should begin with "oArr", followed by one or more digits reflecting that particular array's position within the sequence. Furthermore, I will not know at compile-time how many of these arrays - and hence, how many local variables - I will be needing!
It strikes me that this is perhaps a problem that could be solved by the availability of dynamic types in C# 4.0, however I am not at all familiar with their use. How might I take code like this...
int i=0;
foreach(something)
{
ArrayList oArr+i=new ArrayList();
i++;
}
...and turn it into something that matches the criteria outlined above and actually compiles?
Alternately, is there a more simple, sane approach to this problem?
You cannot change the name of a variable during execution, since the code (even c# code) was compiled with a certain variable name. If you could change the name during execution then it would cause problems.
For example, if the language allowed to change variable names then when you try to access a variable named 'var1' the compiler has no idea if during execution that variable name changed and now is called 'x'.
Something you could try to do is to allow your program to dynamically compile some code but this is probably not the right solution to your problem. If you explain better what you need then we could provide you with an effective solution.
Hope this helped
EDIT: Seeing your editions I can tell you that it is impossible with the approach you are currently using. I could suggest you the following:
int i = 0;
List<ArrayList> masterList = new List<ArrayList>();
foreach (something)
{
masterList.Add(new ArrayList());
i++;
}
If what you need is to have each ArrayList to have a specific name you can recall you can use a dictionary:
int i = 0;
Dictionary<string, ArrayList> masterList = new Dictionary<string, ArrayList>();
foreach (something)
{
masterList.Add("oArr" + i.ToString(), new ArrayList());
i++;
}
ArrayList al = masterList["oArr1"];
Would this work for you?
var arrayLists = new List<ArrayList>();
var i = 0;
foreach(var item in list)
{
arrayLists.Add(new ArrayList());
i++;
}
Then you can access each array list by index.
Use a List of ArrayLists.

Check for Existence of a Result in Linq-to-xml

I'm using Linq-to-XML to do a simple "is this user registered" check (no security here, just making a list of registered users for a desktop app). How do I handle the result from a query like this:
var people = from person in currentDoc.Descendants("Users")
where (string)person.Element("User") == searchBox.Text
select person;
I understand the most common way to use the result would be something like
foreach (var line in people){
//do something here
}
but what do you do if person comes back empty, which is what would happen if the person isn't registered?
I've looked around on this site and on MSDN and haven't found a really clear answer yet.
Extra credit: Give a good explanation of what people contains.
I've read that it's better to use Any() rather than Count()==0 in these situations. E.g
bool anyPeople = people.Any();
if (anyPeople) {
See http://rapidapplicationdevelopment.blogspot.com/2009/07/ienumerablecount-is-code-smell.html for more discussion on the performance impact of using Count() with Linq, especially with IEnumerable, where the entire collection is iterated by the Count() method.
Also using Any() arguably is a clearer explanation of your intent that Count()
Try using:
from person in currentDoc.Descendants("Users")
where (string)person.Element("User") == searchBox.Text && !person.IsEmpty
select person;
The above will select only non-empty person elements. There is also a HasElements property that says whether or not it has any child elements - this may be better to use depending on your XML structure, as blank space make make IsEmpty return false (blank space can count as text).
The people variable is going to be an IEnumerable<XElement> variable, as you appear to be querying a collection of XElement. The var keyword is simply a shortcut to allow it the variable to be typed by the compiler, so you didn't need to figure out the type beforehand and use List<XElement> people = ...
You could just do a people.Count() and if you get 0, you know that person is not registered.
As told by Matt use Count()==0 or Any().
people is IEnumerable<XElement> I think.

Simple form of Array class and Enum.GetValues()

I am working with the static method
Enum.GetValues(typeof(SomeEnum));
This method works great when all you need to do is enumerate the values, but for some reason it returns a very simple form of the Array class. I am trying to find an easy way to turn it's return value into a more "normal" collection class like a regular array or List<>.
So far if I want to do that I have to enumerate through the output of Enum.GetValues(typeof(SomeEnum)); and add them one by one to a List<>.
Any ideas how to do this more cleanly?
Answer:
The key is to cast the return result --
SomeEnum[] enums = (SomeEnum[]) Enum.GetValues(typeof(SomeEnum));
If you need a List then jus wrap it in parenthesis and ToList it like so:
List<SomeEnum> list = ((SomeEnum[]) Enum.GetValues(typeof(SomeEnum))).ToList();
If you're using .NET 3.5, you can also use Cast<T> and ToList extension methods.
IEnumerable<SomeEnum> enums = Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>();
You can also get a list if you want to
List<SomeEnum> list = Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>().ToList();
Inspired by Jon Skeet's unconstrained-melody, I came up with version I like more:
public static class Enum<T>
where T: struct
{
static Enum()
{
Trace.Assert(typeof(T).IsEnum);
Values = Array.AsReadOnly((T[])Enum.GetValues(typeof(T)));
}
public static readonly ReadOnlyCollection<T> Values;
}
and usage:
var values = Enum<BindingFlags>.Values;
Good thing is this version works faster for multiple calls because it does not create new array on every time.
I found here you can just do this:
SomeEnum[] enums = (SomeEnum[]) Enum.GetValues(typeof(SomeEnum));
And if you need a List just use .ToList() at the end, like this:
List<SomeEnum> list = ((SomeEnum[]) Enum.GetValues(typeof(SomeEnum))).ToList();
Or if you like this better:
List<SomeEnum> list2 = new List<SomeEnum>((SomeEnum[]) Enum.GetValues(typeof(SomeEnum)));
I have a brand new library (UnconstrainedMelody) which helps with this. It can return the values in a strongly typed array or in an immutable list:
SomeEnum[] array = Enums<SomeEnum>.GetValuesArray()
IList<SomeEnum> list = Enums<SomeEnum>.GetValues();
It's generic and has a constraint on the type parameter to make sure it's genuinely an enum. This isn't possible in normal C#, but the library does a bit of furtling to make it work. I like the second form more, because we cache the list - the fact that it's immutable means we can return the same reference again and again.
There are various other utility methods to make it easier to work with flags enums etc.
Enjoy.
This should work:
List<MyEnum> enums = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).ToList();
The reason ToList() didn't work in the solution you posted in your question was that you're missing a set of parens around the casted portion. Hope this helps!
REVISION (12-Sep-2009 ~2:20 PM EST):
So, I made this suggestion last night on the basis that Enum.GetValues returns an Array, and I thought that Array implements IEnumerable<T>:
I believe you can construct a
List<T> passing any IEnumerable<T>
as a parameter into the constructor.
So you should be able to just do this:
List<SomeEnum> values = new List<SomeEnum>(Enum.GetValues(typeof(SomeEnum)));
However, GordonG quite promptly replied to my answer indicating that it doesn't compile. (Ordinarily I would test my answer, but I was at a computer without any development tools at the time and was also feeling quite [unreasonably] sure of myself.)
After some downvotes and heavy soul-searching I resolved to get to the bottom of this matter (after a good night's sleep). Turns out, according to Microsoft's documentation on the Array class here, that Array does implement IEnumerable<T>, but only at run time (so, not at compile time--hence the failure to compile). This, in hindsight, makes sense: Enum.GetValues is not a generic method, and so it cannot know what sort of generic collection to return beforehand. (At least that's how I understand it.)
Anyway, what this all means is that you can legally cast an Array to an IEnumerable<T> provided that you get your type right. And so, at last I can present my final answer, which is really the same as my original answer but with a simple cast thrown in to make everything legal:
// splitting into two lines just for readability's sake
List<SomeEnum> values;
values = new List<SomeEnum>((IEnumerable<T>) Enum.GetValues(typeof(SomeEnum)));
Of course, in retrospect, GordonG wasn't dead set on getting a List<T>, which means his own answer of casting to SomeEnum[] is really just as good.
Updated solution (from 'Konstantin Spirin') for .NET framework 2.0:
public static class Enum<T> where T : struct
{
static Enum()
{
Trace.Assert(typeof(T).IsEnum);
}
public static ReadOnlyCollection<T> Values = new ReadOnlyCollection<T>(((T[])Enum.GetValues(typeof(T))));
}
How about this:
List<SomeEnum> list = new List<SomeEnum>();
foreach (SomeEnum value in Enum.GetValues (typeof (SomeEnum)))
{
if (condition)
list.Add(value);
}

Categories