I have created a class which inherits from List: Now I want to iterate the elements of the class in the class itself and return the object if it satisfies certain criteria (e.g. its Property name):
protected class myList : List<Object>
{
getElement(string name)
{
??? LOOP AND IF CONDITION ???
return element;
}
}
Can you help? Thanks
You're looking for foreach(var item in this).
First, I would try to avoid using List<Object>.The problem with Object is, that it needs casting. Hence it is prone to errors at runtime.
Rather create your own class.
For example, a simple item, which holds a name.
class Item
{
public string Name { get; set; }
}
Then you can simply do:
class myList : List<Item>
{
Item getItem(string name)
{
foreach(var item in this)
{
if(item.Name==name) { return item; }
}
return null;
}
}
You'd want some more code for the casting, but:
public Object GetElement(string name)
{
Object element = null;
foreach (var item in this)
{
if (item.ToString() == name)
{
element = item;
break;
}
}
return element;
}
You don't have to reinvent the wheel, just use LINQ.
mylist.First(element => /*criteria*/);
Related
I am trying to find a property of a class in a generic method.
Class abc
-property Name : xyz
I have a method like :
public bool findItem<T> (IEnumerable<T> items) where T : Data
{
if (typeof(T) == typeof(abc))
{
// Code comes inside the loop here
// how to find something like items.First().xyz
}
}
I want to find the property value for the first item but it doesnt work (there is no autosuggest too).
While debugging (in immediate window), I can see my object with class Name when i do items.First().
I tried items.First()["xyz"] but doesnt work. (Cannot apply indexing with [] to an expression of type T)
You certainly could do something like this:
public bool FindItem<T>(IEnumerable<T> items)
{
if (items is IEnumerable<Abc> abcs)
{
int first = abcs.First().Xyz;
return true;
}
else if (items is IEnumerable<Def> defs)
{
int first = defs.First().Ghi;
return true;
}
return false;
}
However, that's not the normal way to do it. Normally you'd just use overloads:
public bool FindItem(IEnumerable<Abc> items)
{
int first = items.First().Xyz;
return true;
}
public bool FindItem(IEnumerable<Def> items)
{
int first = items.First().Ghi;
return true;
}
I had an idea about which I couldn't find any direct syntax. I was wondering if it was possible to overload a reference type so that when it is referenced in a certain way it redirects its reference type into a new one.
I'd like to show an example about this:
public class MyClass
{
public ICollection<int> CollectionProperty { get; private set; }
public MyClass()
{
this.CollectionProperty = new List<int>();
}
}
This is just a simple class, but when MyClass is referenced, for example in a foreach, I'd like it to reference its inner collection like this:
MyClass instance = new MyClass();
foreach(int item in instance)
{
// do stuff
}
So here an item would be an int value of the class's collection's.
It was just something I was curious about, I don't know if it's even possible, maybe with some kind of reference overloading, or I don't know.
Thank you for your answers!
You could implement IEnumerable in order to enable foreach functionality.
public class MyClass<T> : IEnumerable<T>
{
public List<T> Collection { get; set;}
public T this[int index]
{
get { return Collection[index]; }
set { Collection.Insert(index, value); }
}
public IEnumerator<T> GetEnumerator()
{
return Collection.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public MyClass()
{
Collection = new List<T>();
}
}
public class Program
{
public static void Main()
{
var instance = new MyClass<int>();
instance.Collection.Add(1);
instance.Collection.Add(2);
instance.Collection.Add(3);
foreach(int item in instance)
Console.WriteLine(item);
}
}
Output:
1 2 3
So when you get back an list, one value is filled by the repository but the other you want to have the same value for each item in the list. It feels like an for each loop is the a lot of code for simple functionality. Is there a way to shorten the code.
So some context. This is an example class.
public class ExampleClass
{
public string A { get; set; }
public string B { get; set;
}
This is an method that works:
public IEnumerable<ExampleClass> GetAll(string bValue)
{
var exampleList = repo.GetAll(); //Asume that the repo gives back the an list with A filled;
var returnValue = new List<ExampleClass>();
foreach (var item in exampleList)
{
item.B= bValue;
returnValue.Add(item);
}
return returnValue;
}
It would be great if there could something like:
public IEnumerable<ExampleClass> GetAll(string bValue)
{
return repo.GetAll().Map(i => i.B = bValue);
}
Does anyone knows something like this.
You could use yield return:
public IEnumerable<ExampleClass> GetAll(string bValue)
{
foreach (var item in repo.GetAll())
{
item.B = bValue;
yield return item;
}
}
You can also turn this into an extension method for more fluency:
public static class IEnumerableExtensions
{
public static IEnumerable<T> Map<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (var item in source)
{
action(item);
yield return item;
}
}
}
// usage
public IEnumerable<ExampleClass> GetAll(string bValue)
{
return repo.GetAll().Map(x => x.B = bValue);
}
You can try LINQ. According to this link:
Update all objects in a collection using LINQ , you can do this:
repo.getAll().Select(c => {c.B = value; return c;}).ToList();
However, according to Jon Skeet, it's better to just use Foreach loop.
https://stackoverflow.com/a/7851940/5779825
return repo.GetAll().ToList().ForEach(i => i.B = bValue);
This should work. Not tested though.
I think you can use this approach:
return exampleList.Select(i => { i.B = bValue; return i; });
I have a base class:
public abstract class BaseClass{
public bool IsSelected {get; set;}
}
A derived class with a collection representing a hierarchy:
public class DerivedOne : BaseClass{
public ObservableCollection<BaseClass> Children {get; set;}
}
Another derived class:
public class DerivedTwo : BaseClass{
}
What is the simplest way to find all of the elements under a DerivedOne root that have IsSelected set to true?
You left out some requirement detail, but I think something like this should work:
public IEnumerable<BaseClass> AllIsSelected(BaseClass root)
{
if (root.IsSelected)
{
yield return root;
}
var composite = root as DerivedOne;
if (composite != null)
{
foreach (var v in composite.Children)
{
foreach (var x in AllIsSelected(v))
{
yield return x;
}
}
}
}
Of course, if you want a full list all at once, you could build the list instead of using 'yield'.
This is the same design discussed here: IEnumerable and Recursion using yield return.
As another answer said, you can use LINQ to shorten this somewhat. This version avoids making the temporary list.
public IEnumerable<BaseClass> AllIsSelected(BaseClass root)
{
if (root.IsSelected)
{
yield return root;
}
var composite = root as DerivedOne;
if (composite != null)
{
foreach (var x in composite.Children.SelectMany(v => AllIsSelected(v)))
{
yield return x;
}
}
}
The simplest method would be to use LINQ with recursion
public IEnumerable<BaseClass> GetAllSelectedChildren(DerivedOne derivedOne)
{
return derivedOne.Children.SelectMany(GetAllSelected);
}
public IEnumerable<BaseClass> GetAllSelected(BaseClass baseClass)
{
var selected = new List<BaseClass>();
if(baseClass.IsSelected)
{
selected.Add(baseClass);
}
var derivedOne = baseClass as DerivedOne;
if(derivedOne != null)
{
selected.AddRange(GetAllSelectedChildren(derivedOne));
}
return selected;
}
Use simple Linq.
return root.Children
.SelectMany(c => new[]{ c }.Concat(c.Children)) // flatten the structure including self node.
.Where(e => e.IsSelected) // filter selected items
.ToList();
So for a type like:
CoolCollection<T>
you could have:
foreach (T item in coolCollection)
{
...
}
foreach (CoolNode node in coolCollection)
{
...
}
If this isn't possible, maybe like foreach2, or some other way to iterate. Often times, I would really like more than 1 way of iterating on a type.
EDIT: Sorry if it wasn't clear. Basically CoolNode is a node that makes CoolCollection. CoolNode has a property called value to return T, but I need another iterator to return only CoolNodes.
EDIT2: I can't do coolCollection.Something to iterate, because CoolNodes are connected via a property called Next, like a LinkedList. So I need to implement 2 iterators.
Just make CoolCollection<T> explicitly implement IEnumerable<CoolNode<T>> as well as IEnumerable<T>. (I'm guessing it's really CoolNode<T>, but if not, just take the extra <T> out everywhere.)
This will let you iterate in both manners, although you'll need a cast.
To do this, you'd need something like:
class CoolCollection<T> : ICollection<T>, IEnumerable<CoolNode<T>>
{
IEnumerator<CoolNode<T>> IEnumerable<CoolNode<T>>.GetEnumerator()
{
///...Do work here...
}
IEnumerator<T> GetEnumerator()
{
///...Do work here...
}
}
Using this would be like so:
foreach (T item in coolCollection)
{
...
}
foreach (CoolNode<T> node in (IEnumerable<CoolNode<T>>)coolCollection)
{
...
}
The other option would be to expose a property for the "nodes", so you could do:
foreach(var nodes in coolCollection.Nodes)
{ ... }
To implement this, you'd change things around a little bit. You'd need to make a private class that implemented the enumerator... something like:
class CoolCollection<T> : ICollection<T>
{
private List<CoolNode<T>> nodes;
IEnumerable<CoolNode<T>> Nodes
{
get
{
foreach(var node in this.nodes) { yield return node; }
}
}
}
If I understand the question correctly...
You could do it similar to the some of the other collection objects do it:
for example:
foreach (int key in IDictionary.Keys)
{
}
foreach (object value in IDictionary.Values)
{
}
But I don't think there is a way to do exactly the way you have it written...
No, you can't do that. You can not overload your default iterator.
Imagine if you could overload your default iterator.
What would this do? foreach (object o in foo) , there would be no logical way to choose the right iterator.
What you can do is have a second method named ForEach2 that iterates through your collection in a different way. Or you could explicitly implement an interface. Or you could use Linq composition for this kind of stuff.
From a class design perspective:
interface IBar {
IEnumerator<string> GetEnumerator();
}
class Foo : IBar, IEnumerable<int> {
// Very bad, risky code. Enumerator implementations, should
// line up in your class design.
public IEnumerator<int> GetEnumerator()
{
yield return 1;
yield return 2;
yield return 3;
yield return 4;
}
IEnumerator<string> IBar.GetEnumerator()
{
yield return "hello";
}
// must be IEnumerable if you want to support foreach
public IEnumerable<string> AnotherIterator
{
get {
yield return "hello2";
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
LINQ extensions for EachPair
struct Pair<T> {
public T First;
public T Second;
}
static class LinqExtension {
public static IEnumerable<Pair<T>> EachPair<T>(this IEnumerable<T> input) {
T first = default(T);
bool gotFirst = false;
foreach (var item in input)
{
if (!gotFirst)
{
first = item;
gotFirst = true;
}
else {
yield return new Pair<T>() { First = first, Second = item };
gotFirst = false;
}
}
}
}
Test code:
class Program
{
static void Main(string[] args)
{
var foo = new Foo();
foreach (int number in foo)
{
Console.WriteLine(number);
}
// LINQ composition - a good trick where you want
// another way to iterate through the same data
foreach (var pair in foo.EachPair())
{
Console.WriteLine("got pair {0} {1}", pair.First, pair.Second);
}
// This is a bad and dangerous practice.
// All default enumerators should be the same, otherwise
// people will get confused.
foreach (string str in (IBar)foo)
{
Console.WriteLine(str);
}
// Another possible way, which can be used to iterate through
// a portion of your collection eg. Dictionary.Keys
foreach (string str in foo.AnotherIterator)
{
Console.WriteLine(str);
}
}
If CoolCollection implements IEnumerable you can write:
foreach (var item in coolCollection)
{
...
}
or if T is CoolNode
foreach (CoolNode node in coolCollection)
{
...
}
If you need somehow transform each item to your type, you can use Linq Select operator:
foreach (CoolNode node in coolCollection.Select(item => ConvertToNode(item))
{
...
}
Take a look at the iterindex snippet. In your class, type iterindex and hit [TAB]. It will help you implement a "Named Iterator and Indexer" pattern.
The result can by used like this:
foreach (var e in myTree.DepthFirstView) // supports iteration
{
if (e == myTree.DepthFirstView[2]) // supports indexing
{
// ...
}
}
(I wrote this snippet, but I suspect it has never been put to good use. Ever.)