Easier way to systematically create new nodes? - c#

So for testing purposes I need to have three IEnumerables of type <T>. One with both branches, one with one branch, and one comprising of just the node. I have to create further tests in much larger tree structures that will require more iterations of different IEnumerables. Currently, my (working) solution looks something like this. But I can't help but think that I could be adding the branches one at a time and setting the IEnumerables equal to one another at each step, or something of that nature to speed up the process. Evidently a direct implementation of this wouldn't work as they are reference types so they'll end up with the same value anyways, and it would be rather messy anyhow, if I worked around it...leaving me a bit stuck. Is there any way to accomplish this in less cumbersome fashion?
// Create test IEnumerables for comparison (one full, one with one branch, one of just node)
List<T> testlistfull, testlist1branch, testlistnode;
testlistnode = new List<T>();
testlistnode.Add(node0);
testlist1branch = new List<T>();
testlist1branch.Add(node0);
testlist1branch.Add(branch1);
testlistfull = new List<T>();
testlistfull.Add(node0);
testlistfull.Add(branch1);
testlistfull.Add(branch2);
IEnumerable<T> testenumfull = testlistfull as IEnumerable<T>;
IEnumerable<T> testenum1branch = testlist1branch as IEnumerable<T>;
IEnumerable<T> testenumnode = testlistnode as IEnumerable<T>;

You could use implicitly typed arrays. They infer their type from the values in the array initializer.
IEnumerable<T> testenumfull = new [] {node0, branch1, branch2};
IEnumerable<T> testenum1branch = new [] {node0, branch1};
IEnumerable<T> testenumnode = new [] {node0};
Or if they have to be of type List<T> for some reason.
IEnumerable<T> testenumfull = new List<T>{node0, branch1, branch2};
IEnumerable<T> testenum1branch = new List<T>{node0, branch1};
IEnumerable<T> testenumnode = new List<T>{node0};
You don't need the as IEnumerable<T> as simply assigning to a variable of that type will do the implicit cast.

Related

LINQ for System.Collections.IEnumerable

LINQ Where() works with System.Collections.Generic.IEnumerable<T> but cant be used if the implemented interface is System.Collections.IEnumerable
My question is, why is that so?
Update:
Maybe a little bit of context, I want to use .Where() on the Transform class of Unity, which implements System.Collections.IEnumerable instead of System.Collections.Generic.IEnumerable<Transform> even though it only has Transforms as children..
So I now created an extension method for Transform, feel free to use it:
/// <summary> Where-Filter implementation for transform to filter out specific children</summary>
public static IEnumerable<GameObject> WhereChild(this Transform s, Func<GameObject, bool> callback) {
List<GameObject> r = new List<GameObject>();
foreach (Transform cur in s) { if (callback(cur.gameObject)) { r.Add(cur.gameObject); } }
return r;
}
(Modify it if you want to work on the transforms and not the children Gameobjects instead, I like it more this way;)
Because most of those methods are generic and make little sense when you only get objects. A few methods are in fact declared as extension methods on IEnumerable instead of IEnumerable<T>, e.g. Cast<T>() and OfType<T>, both of which return a typed enumerable.
So in your case you can use Cast<object>() to reap the benefits of LINQ in the most useless manner, because the predicate for Where cannot really reasonably do much with an object without casting it anyway.
Non generic collections where you can't really say anything about items more that they are just objects won't let you write useful predicates. And these are required by linq operators.
Suppose
IEnumerable e = ...;
e.Where( item => ?? );
Here item is of type object and you are pretty much stuck.
On the other hand
IEnumerable<Person> e = ...;
e.Where( item => ?? );
Here you can refer to whatever members the actual type contains.
Note that you can always "upcast" collections
IEnumerable e = ...;
e.OfType<Person>().Where( ... )
The OfType operator makes a generic collection of these items of a non generic collection that are of given type. Thus it allows you to introduce strong typing and use typed operators further the line.

Upcasting Generics

Ok, I know this is impossible, but I'm wondering if anyone knows of a way to get around this.
List<int> numberList = new List<int>();
List<object> objectList = (List<object>)numberList;
This generates the following error:
Cannot convert type 'System.Collections.Generic.List{int}' to 'System.Collections.Generic.List{object}'
This is a simple example, but here is my real problem. I have a method that dynamically generates an IQueryable{IGrouping{TKey, TElement}} instance. However, since in my case TKey is dynamically generated, I can only return an IQueryable to the caller.
I want to be able to return an IQueryable{IGrouping{dynamic, TElement}} to the caller. However, the compiler complains because just like in my first example, its casting TKey as an object (for dynamic), and won't let me cast it that way. Is there any way around that?
Update:
Here is a closer example of what I'm trying to solve:
List<int> testList = new List<int>();
var qry = new EnumerableQuery<int>( testList );
var objectQry = (IQueryable<object>)qry;
While this example doesn't produce a compile-time error, is does produce a casting exception when you try to run it. For some reason, even though IQuerable is covariant (thanks Servy for your comments on that), once I introduce an implementing class such as EnumerableQuery, it fails.
Try this.
List<int> numberList = new List<int>();
List<object> objectList = numberList.Cast<object>().ToList();
Enumerable.Cast<T>
Casts the elements of an IEnumerable to the specified type.
You need to construct a copy of each new dictionary, because dictionaries as well as lists are not covariant with respect to any of their generic arguments.
(The keys are also provided in output through the Keys property, and the sequence of pairs itself, so even IDictionary<TKey, TValue> cannot be covariant with respect to TKey.)
You can use Select to map each object to a new object:
List<Dictionary<int, string>> listOfDicts = new List<Dictionary<int, string>>();
List<Dictionary<object, string>> newList = listOfDicts.Select(dic =>
dic.ToDictionary(pair => (object)pair.Key, pair => pair.Value))
.ToList();
IQueryable<T> on the other hand is covariant, as is IGrouping, so you can cast interfaces of those types up:
IQueryable<IGrouping<dynamic, int>> query = null;
IQueryable<IGrouping<object, int>> otherQuery = query;
That compiles and runs just fine.

How to get an empty list of a collection?

I have a collection of anonymous class and I want to return an empty list of it.
What is the best readable expression to use?
I though of the following but I don't think they are readably enough:
var result = MyCollection.Take(0).ToList();
var result = MyCollection.Where(p => false).ToList();
Note: I don't want to empty the collection itself.
Any suggestion!
Whats about:
Enumerable.Empty<T>();
This returns an empty enumerable which is of type T. If you really want a List so you are free to do this:
Enumerable.Empty<T>().ToList<T>();
Actually, if you use a generic extension you don't even have to use any Linq to achieve this, you already have the anonymous type exposed through T
public static IList<T> GetEmptyList<T>(this IEnumerable<T> source)
{
return new List<T>();
}
var emp = MyCollection.GetEmptyList();
Given that your first suggestion works and should perform well - if readability is the only issue, why not create an extension method:
public static IList<T> CreateEmptyCopy(this IEnumerable<T> source)
{
return source.Take(0).ToList();
}
Now you can refactor your example to
var result = MyCollection.CreateEmptyCopy();
For performance reasons, you should stick with the first option you came up with.
The other one would iterate over the entire collection before returning an empty list.
Because the anonymous type there is no way, in source code, to create a list. There is, however, a way to create such list through reflection.

What is the best way to cast from ArrayList to List in .Net 2.0

I have a ArrayList of type BookingData to List<BookingData> ?
I am using .net 2.0 so i cannot use arrayList.Cast<int>().ToList() , and I dont want to make here foreach loop , do you have better ideas ?
Thanks.
Do note that something is going to have to enumerate the array-list to construct the List<T>; its only a matter of whether you do it yourself or leave it to some other (framework / utility) method.
If this is a one-off, the solution that you wish to avoid (using an "in-place" foreach loop to do the conversion) is a perfectly reasonable option. If you find yourself doing this quite often, you could extract that out into a generic utility method, as in cdhowie's answer.
If your restriction is only that you must target .NET 2.0 (but can use C# 3), consider LINQBridge, which is a reimplementation of LINQ to Objects for .NET 2.0. This will let you use the Cast sample you've provided without change. It will work on C# 2 too, but you won't get the benefits of the extension-method syntax, better type-inference etc.
If you don't care about performance, nor do you want to go to the trouble of writing a utility method, you could use the in-built ArrayList.ToArray method to help out, by creating an intermediary array that plays well with List<T> (this isn't all that shorter than a foreach):
ArrayList arrayList = ...
// Create intermediary array
BookingData[] array = (BookingData[]) arrayList.ToArray(typeof(BookingData));
// Create the List<T> using the constructor that takes an IEnumerable<T>
List<BookingData> list = new List<BookingData>(array);
Finally, I would suggest, if possible to abandon using the obsolete non-generic collection-classes altogether.
Let's keep it simple:
// untested
List<T> ConvertArrayList<T>(ArrayList data)
{
List<T> result = new List<T> (data.Count);
foreach (T item in data)
result.Add(item);
return result;
}
...
List<BookingData> newList = ConvertArrayList<BookingData>(oldList);
Use this method:
public static List<T> ConvertToList<T>(ArrayList list)
{
if (list == null)
throw new ArgumentNullException("list");
List<T> newList = new List<T>(list.Count);
foreach (object obj in list)
newList.Add((T)obj);
// If you really don't want to use foreach:
// for (int i = 0; i < list.Count; i++)
// newList.Add((T)list[i]);
return newList;
}
Then you can:
List<BookingData> someList = ConvertToList<BookingData>(someArrayList);
You have to use foreach:
foreach (Object item in list1)
{
list2.Add((BookingData)item);
}
ToList() method is nothing but the Synthetic sugar for creating a List representation but internally it is also using loop to generate the list item.
so it is much cleaner and simpler to use a foreach iterator block.

C#: Union of two ICollections? (equivalent of Java's addAll())

I have two ICollections of which I would like to take the union. Currently, I'm doing this with a foreach loop, but that feels verbose and hideous. What is the C# equivalent of Java's addAll()?
Example of this problem:
ICollection<IDictionary<string, string>> result = new HashSet<IDictionary<string, string>>();
// ...
ICollection<IDictionary<string, string>> fromSubTree = GetAllTypeWithin(elementName, element);
foreach( IDictionary<string, string> dict in fromSubTree ) { // hacky
result.Add(dict);
}
// result is now the union of the two sets
You can use the Enumerable.Union extension method:
result = result.Union(fromSubTree).ToList();
Since result is declared ICollection<T>, you'll need the ToList() call to convert the resulting IEnumerable<T> into a List<T> (which implements ICollection<T>). If enumeration is acceptable, you could leave the ToList() call off, and get deferred execution (if desired).
AddRange() appends the source list to the end of another, and may suit your needs.
destList.AddRange(srcList);
LINQ's Enumerable.Union will work:

Categories

Resources