I have this class, wherein I want to implement IEnumerable to be able to use foreach().
Here is my code by i think i'm not doing it correctly
public class SearchResult : IEnumerable<SearchResult>
{
string Name { get; set; }
int Rating { get; set; }
public IEnumerator<SearchResult> GetEnumerator()
{
return( this );
}
}
You could do:
public IEnumerator<SearchResult> GetEnumerator()
{
yield return this;
}
However it's unusual for an object like this to implement IEnumerable<T> and return itself in a single-element sequence.
You might want to create a utility method instead:
public static IEnumerable<T> ToSequence<T>(T instance)
{
reutrn new[] { instance };
}
If you really truly swear that you need to do this:
SearchResult justOne = ... blah ...;
foreach (SearchResult eachOne in justOne) {
... blah ...
}
Then you could do this minor modification to your method (use yield return instead of return):
public IEnumerator<SearchResult> GetEnumerator()
{
yield return( this );
}
Related
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
I'm having some trouble creating my own List structure. I'm trying to create a List structure called SortedList. The objective is for it to Sort its items as soon as add a new item. This list will not get too big in the project I'm using it for (maybe 50-100 items at most). However, I was testing by adding a simple item of class Employee which has a Name property. And I want this SortedList to sort on employee's Name.
Here is my attempt.
The Employee class
public class Employee : IComparer<Employee>
{
public string Name { get; set; }
public Employee()
{
}
public int Compare(Employee x, Employee y)
{
return string.Compare(x.Name, y.Name,true);
}
}
Here is the SortedList class that I'm trying to create.
public class SortedList<T> : IEnumerable<T>
{
private List<T> _list;
public List<T> List
{
get { return _list; }
set { _list = value; }
}
private Employee EmployeeComparer = new Employee();
public SortedList()
{
_list = new List<T>();
}
public void Insert(T item)
{
if (!_list.Contains(item))
{
_list.Add(item);
Sort(_list);
}
}
private void Sort(List<T> list)
{
var type = typeof(T);
switch (type.Name)
{
case "Int32":
case "String":
list.Sort();
break;
case "Employee":
Employee EmployeeComparer = new Employee();
list.Sort(EmployeeComparer);
break;
}
}
public IEnumerator<T> GetEnumerator()
{
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
From program.cs I'm basically populating the SortedList with three instances of Employee objects and I expect it to Sort it by employee's Name property and in the out put I expect to see this.
Barry
Neil
Zach
class Program
{
static void Main(string[] args)
{
SortedList<Employee> list = new SortedList<Employee>();
list.Insert(new Employee() { Name="Zach"});
list.Insert(new Employee() { Name = "Neil" });
list.Insert(new Employee() { Name = "Barry" });
foreach (var item in list)
{
Console.WriteLine(item.Name);
}
}
}
But I get a compiler error. It says:
Severity Code Description Project File Line Suppression State
Error CS1503 Argument 1: cannot convert from 'ExtensingLists.Employee' to 'System.Collections.Generic.IComparer<T>' ExtensingLists C:\E Drive\VSProjects\C-Sharp Generics Course\ExtensingLists\ExtensingLists\SortedList.cs 57 Active
The error says line 57, which is this:
list.Sort(EmployeeComparer);
What am I doing wrong? Please advise. Thank you.
The concrete question you're asking about is like asking why
int f(object o) { return o is int ? o : 0; }
fails to compile. Even if you've checked that o has type int at run-time, at compile-time it still has type object, which means it can't be used as the return value. You'd need a cast to get that working:
int f(object o) { return o is int ? (int)o : 0; }
and the same applies to your code.
But there's something more fundamentally wrong. Your Employee shouldn't be implementing IComparer<Employee>. It should be implementing IComparable<Employee>, which specifies not that an Employee object knows how to compare two other Employee objects, but that it knows how to compare itself to another Employee object. And when you do that, you should be able to just call list.Sort(); without checking the type at all.
The List.Sort method can be made to work in multiple ways.
This method uses the default comparer Comparer.Default for type T to determine the order of list elements. The Comparer.Default property checks whether type T implements the IComparable generic interface and uses that implementation, if available. If not, Comparer.Default checks whether type T implements the IComparable interface. If type T does not implement either interface, Comparer.Default throws an InvalidOperationException.
So by making the below change, it will start working for you
public class Employee : IComparable<Employee> {
public string Name { get; set; }
public Employee() {
}
public int CompareTo(Employee other) {
return string.Compare(Name, other.Name, true);
}
}
and the Below change in public class SortedList<T> : IEnumerable<T> {
private static void Sort(List<T> list) {
var type = typeof(T);
list.Sort();
}
This is not the only way to do, but a preferable way to do when the Types are intrinsically Orderable. You can also use the IComparer<T> interface, but that is used when the Type needs to be sorted in a way that IComparable<T> does not or when the Type is not an IComparable<T>. I have listed all the code here together
class Program {
static void Main() {
SortedList<Employee> list = new SortedList<Employee>();
list.Insert(new Employee() { Name = "Zach" });
list.Insert(new Employee() { Name = "Neil" });
list.Insert(new Employee() { Name = "Barry" });
foreach (var item in list) {
Console.WriteLine(item.Name);
}
}
}
public class Employee : IComparable<Employee> {
public string Name { get; set; }
public int Age { get; set; }
public Employee() {
}
public int CompareTo(Employee other) {
return string.Compare(Name, other.Name, true);
}
}
public class EmployeeAgeComparer : IComparer<Employee> {
public int Compare(Employee x, Employee y) {
return x.Age - y.Age;
}
}
public class SortedList<T> : IEnumerable<T> {
private List<T> _list;
public List<T> List {
get { return _list; }
set { _list = value; }
}
private EmployeeAgeComparer EmployeeComparer = new EmployeeAgeComparer();
public SortedList() {
_list = new List<T>();
}
public void Insert(T item) {
if (!_list.Contains(item)) {
_list.Add(item);
Sort(_list);
}
}
private void Sort(List<T> list) {
if (typeof(T) == typeof(Employee))
list.Sort((IComparer<T>)EmployeeComparer);
else
list.Sort();
}
public IEnumerator<T> GetEnumerator() {
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
I have auto generated by the VS wrapper for WMI collection witch looks like this:
// Enumerator implementation for enumerating instances of the class.
public class DiskDriveCollection : object, ICollection {
private ManagementObjectCollection privColObj;
public DiskDriveCollection(ManagementObjectCollection objCollection) {
privColObj = objCollection;
}
public virtual int Count {
get {
return privColObj.Count;
}
}
public virtual bool IsSynchronized {
get {
return privColObj.IsSynchronized;
}
}
public virtual object SyncRoot {
get {
return this;
}
}
public virtual void CopyTo(System.Array array, int index) {
...
}
public virtual System.Collections.IEnumerator GetEnumerator() {
return new DiskDriveEnumerator(privColObj.GetEnumerator());
}
public class DiskDriveEnumerator : object, System.Collections.IEnumerator {
private ManagementObjectCollection.ManagementObjectEnumerator privObjEnum;
public DiskDriveEnumerator(ManagementObjectCollection.ManagementObjectEnumerator objEnum) {
privObjEnum = objEnum;
}
public virtual object Current {
get {
return new DiskDrive(((System.Management.ManagementObject)(privObjEnum.Current)));
}
}
public virtual bool MoveNext() {
return privObjEnum.MoveNext();
}
public virtual void Reset() {
privObjEnum.Reset();
}
}
}
How can I use except operator with this non generic ICollection?
ICollection inherits from IEnumerable, and there is an OfType method which takes an IEnumerable and returns IEnumerable<T>, then you can easily use all LINQ methods when you got IEnumerable<T>, for example:
myCollection.OfType<object>()
.Except(myOtherCollection.OfType<object>(), new CustomEqualityComparer());
Since you have objects, you need to implement an equality comparer for them an pass it to Except method, otherwise Except will compare your object by references.
Here is my problem: there is a class that contains a inner collection (or list, or array, or something like this) of some some class and It must expose a public read-only collection of items, which are properties (or fields) of relative items in inner collection. For example:
//Inner collection consists of items of this class
class SomeClass
{
public int _age;
//This property is needed for exposing
public string Age { get { return this._age.ToString(); } }
}
//Keeps inner collection and expose outer read-only collection
class AnotherClass
{
private List<SomeClass> _innerList = new List<SomeClass> ();
public ReadOnlyCollection<string> Ages
{
get
{
//How to implement what i need?
}
}
}
I know a simple way to do this by the use of a pair of inner lists, where the second keeps values of needed properties of first. Something like this:
//Inner collection consists of items of this class
class SomeClass
{
public int _age;
//This property is needed for exposing
public string Age { get { return this._age.ToString(); } }
}
//Keeps inner collection and expose outer read-only collection
class AnotherClass
{
private List<SomeClass> _innerList = new List<SomeClass> ();
private List<string> _innerAgesList = new List<string> ();
public ReadOnlyCollection<string> Ages
{
get
{
return this._innerAgesList.AsreadOnly();
}
}
}
But I dislike this overhead. May be there is some way to do what I want with exposing interfaces. Help me, please!
Hurra!
It seems that the best solution has been found. Due to the post of Groo
this problem found its almost universal answer. Here is It (we need to add two entity):
public interface IIndexable<T> : IEnumerable<T>
{
T this[int index] { get; }
int Count { get; }
}
class Indexer <Tsource, Ttarget> : IIndexable<Ttarget>
{
private IList<Tsource> _source = null;
private Func<Tsource, Ttarget> _func = null;
public Indexer(IList<Tsource> list, Func<Tsource, Ttarget> projection)
{
this._source = list;
this._func = projection;
}
public Ttarget this[int index] { get { return this._func(this._source[index]); } }
public int Count { get { return _source.Count; } }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public IEnumerator<Ttarget> GetEnumerator()
{ foreach (Tsource src in this._source) yield return this._func(src); }
}
With them, our implementation looks like this:
//Inner collection consists of items of this class
class SomeClass
{
public int _age;
//This property is needed for exposing
public string Age { get { return this._age.ToString(); } }
}
//Keeps inner collection and expose outer read-only collection
class AnotherClass
{
private List<SomeClass> _innerList = new List<SomeClass> ();
private Indexer<SomeClass, string> _indexer = null;
public AnotherClass ()
{ this._indexer = new Indexer<SomeClass, string > (this._innerList, s => s.Age); }
public IIndexable<string> Ages { get { return this._indexer; } }
}
Thank Groo and the rest who answered. Hope, this helps someone else.
The overhead is not so significant if you consider that ReadOnlyCollection is a wrapper around the list (i.e. it doesn't create a copy of all the items).
In other words, if your class looked like this:
class AnotherClass
{
private ReadOnlyCollection<string> _readonlyList;
public ReadOnlyCollection<string> ReadonlyList
{
get { return _readonlyList; }
}
private List<string> _list;
public List<string> List
{
get { return _list; }
}
public AnotherClass()
{
_list = new List<string>();
_readonlyList = new ReadOnlyCollection<string>(_list);
}
}
Then any change to the List property is reflected in the ReadOnlyList property:
class Program
{
static void Main(string[] args)
{
AnotherClass c = new AnotherClass();
c.List.Add("aaa");
Console.WriteLine(c.ReadonlyList[0]); // prints "aaa"
c.List.Add("bbb");
Console.WriteLine(c.ReadonlyList[1]); // prints "bbb"
Console.Read();
}
}
You may have issues with thread safety, but exposing IEnumerable is even worse for that matter.
Personally, I use a custom IIndexable<T> interface with several handy wrapper classes and extension method that I use all over my code for immutable lists. It allows random access to list elements, and does not expose any methods for modification:
public interface IIndexable<T> : IEnumerable<T>
{
T this[int index] { get; }
int Length { get; }
}
It also allows neat LINQ-like extension methods like Skip, Take and similar, which have better performance compared to LINQ due to the indexing capability.
In that case, you can implement a projection like this:
public class ProjectionIndexable<Tsrc, Ttarget> : IIndexable<Ttarget>
{
public ProjectionIndexable
(IIndexable<Tsrc> src, Func<Tsrc, Ttarget> projection)
{
_src = src;
_projection = projection;
}
#region IIndexable<Ttarget> Members
public Ttarget this[int index]
{
get { return _projection(_src[index]); }
}
public int Length
{
get { return _src.Length; }
}
#endregion
#region IEnumerable<Ttarget> Members
// create your own enumerator here
#endregion
}
And use it like this:
class AnotherClass
{
private IIndexable<string> _readonlyList;
public IIndexable<string> ReadonlyList
{
get { return _readonlyList; }
}
private List<SomeClass> _list;
public List<SomeClass> List
{
get { return _list; }
}
public AnotherClass()
{
_list = new List<SomeClass>();
_readonlyList = new ProjectionIndexable<SomeClass, string>
(_list.AsIndexable(), c => c.Age);
}
}
[Edit]
In the meantime, I posted an article describing such a collection on CodeProject. I saw you've implemented it yourself already, but you can check it out nevertheless and reuse parts of the code where you see fit.
Why don't you just return IEnumerable?
If you have access to LINQ (.NET 3.5) then just use a select()
public IEnumerable<string> Ages{
get{
return _innerList.Select(s => s.stringProperty);
}
}
in this case I normaly just use IEnumerable - if the collection is readonly and you don't need the Index-functionality you can just do somehting like this:
public IEnumerable<string> Ages
{
get
{
return this._innerList.Select(someObj => someObj.Age).ToArray();
}
}
I have a DataSource in my control which is always a List<T> where T has to inherit from IEntity.
public class MyClass<T> where T : IEntity
{
public List<T> DataSource
{
get;
set;
}
}
Now, obviously you can't cast a List<T> to a List<IEntity> doing the following:
List<IEntity> wontWork = (List<IEntity>)this.DataSource;
How can I get the DataSource as a List of IEntity, whilst still being able to add and remove items from the DataSource? I.e. I could do the following, but removing from the List it returns would not remove from the DataSource:
public List<TOut> GetDataSourceCopyAsUnderlyingType<TOut>()
{
if (this.DataSource == null)
{
return new List<TOut>();
}
else
{
// Get the list and the enumerator
IList list = (IList)this.DataSource;
IEnumerator enumerator = list.GetEnumerator();
// Build the target list
List<TOut> targetList = new List<TOut>();
int i = 0;
while (enumerator.MoveNext())
{
TOut entity = (TOut)list[i];
targetList.Add(entity);
i++;
}
return targetList;
}
}
Basically, I need some way of doing the following:
List<IEntity> interfaceList = this.GetDataSourceAsAnotherType<IEntity>();
int dataSourceCount = this.DataSource.Count; // Equals 5
int interfaceCount = interfaceList.Count; // Equals 5
interfaceList.RemoveAt(0);
int dataSourceCount = this.DataSource.Count; // Equals 4
int interfaceCount = interfaceList.Count; // Equals 4
And just to add, I don't mind if it means I've got to use a different type instead of a List.
EDIT: Sorry, forgot to say I'm using .Net2.0 and cannot move to .Net 3.5.
It would be a monumentally bad idea if this were allowed, which is why it isn't. I can add any old IEntity to a List<IEntity> which will blow up if that IEntity can't be cast to T. Whilst all Ts are IEntities, not all IEntities are Ts.
This works with arrays because arrays have a deliberate subtyping hole (as they do in Java). Collections do not have a subtyping hole.
Create a wrapper class that seamlessly converts. Untested sample:
public class CastList<TTarget, TOriginal>
: IList<TTarget> where TOriginal : TTarget
{
List<TOriginal> _orig;
public CastList(List<TOriginal> orig) { _orig = orig; }
public Add(TTarget item) { _orig.Add(item); }
public TTarget this[int i]
{
get { return (TTarget)_orig[i]; }
set { _orig[i] = value; }
}
public IEnumerator<TTarget> GetEnumerator()
{
foreach(TOriginal item in _orig)
yield return (TTarget)item;
}
// etc...
}
Manipulations of the original list will also be reflected in the wrapper. To use this, just construct it with your DataSource.
What DrPizza said, but with more code:
public class ListFacade<TIn, TOut> : IList<TOut> where TIn : TOut
{
private readonly IList<TIn> innerList;
public ListFacade(IList<TIn> innerList)
{
this.innerList = innerList;
}
public int Count
{
get { return this.innerList.Count; }
}
public bool IsReadOnly
{
get { return this.innerList.IsReadOnly; }
}
public TOut this[int index]
{
get { return this.innerList[index]; }
set { this.innerList[index] = (TIn)value; }
}
public void Add(TOut item)
{
this.innerList.Add((TIn)item);
}
public void Clear()
{
this.innerList.Clear();
}
public bool Contains(TOut item)
{
return (item is TIn) && this.innerList.Contains((TIn)item);
}
public void CopyTo(TOut[] array, int arrayIndex)
{
var inArray = new TIn[this.innerList.Count];
this.innerList.CopyTo(inArray, arrayIndex);
Array.Copy(inArray, array, inArray.Length);
}
public IEnumerator<TOut> GetEnumerator()
{
foreach (var item in this.innerList)
{
yield return item;
}
}
System.Collections.IEnumerator
System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public int IndexOf(TOut item)
{
return (item is TIn) ? this.innerList.IndexOf((TIn)item) : -1;
}
public void Insert(int index, TOut item)
{
this.innerList.Insert(index, (TIn)item);
}
public bool Remove(TOut item)
{
return (item is TIn) && this.innerList.Remove((TIn)item);
}
public void RemoveAt(int index)
{
this.innerList.RemoveAt(index);
}
Add, Insert and the indexer set will blow up if the argument is not of type TIn.
ok this might be completely beside the point but, how about using a little bit of Linq?
var interfaceList = objectList.ConvertAll<Interface>(o => (Interface)o);
this way you can cast the objectList easily.
hope this helps to find the solution...
I'm in favor of linq too, but you can do it like:
var interfaceList = objectList.Cast<IEntity>();
Which is shorter and more expressive.