Understanding C# Field Initialization Requirements

Troubles implementing IEnumerableT

Since IEnumerable<T> implements IEnumerable you need to implement this interface as well in your class which has the non-generic version of the GetEnumerator method. To avoid conflicts you could implement it explicitly:

IEnumerator IEnumerable.GetEnumerator()
{
// call the generic version of the method
return this.GetEnumerator();
}

public IEnumerator<T> GetEnumerator()
{
for (int i = 0; i < Count; i++)
yield return _array[i];
}

How to implement IEnumerableT with GetEnumerator()?

You're missing IEnumerator IEnumerable.GetEnumerator():

public class Simulation : IEnumerable<string>
{
private IEnumerable<string> Events()
{
yield return "a";
yield return "b";
}

public IEnumerator<string> GetEnumerator()
{
return Events().GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}

custom collection cannot implement IEnumerableT

Because IEnumerable<T> inherits from IEnumerable, you need to implement the non-generic GetEnumerator() as well. Add this to your class:

IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}

How do I implement IEnumerableT

If you choose to use a generic collection, such as List<MyObject> instead of ArrayList, you'll find that the List<MyObject> will provide both generic and non-generic enumerators that you can use.

using System.Collections;

class MyObjects : IEnumerable<MyObject>
{
List<MyObject> mylist = new List<MyObject>();

public MyObject this[int index]
{
get { return mylist[index]; }
set { mylist.Insert(index, value); }
}

public IEnumerator<MyObject> GetEnumerator()
{
return mylist.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}

LINQ gets confused when implementing IEnumerableT twice

It's important to understand that the compiler has no concept of "primary" and "secondary" interface implementations when it comes to using an expression as an argument for a method call. Your type implements both IEnumerable<IAssociation<...>> and IEnumerable<KeyValuePair<...>> equally well, as far as conversions to those types are concerned. That's why the compiler needs more information.

The simplest approach (IMO) would be to introduce two new properties:

public IEnumerable<IAssociation<TKey, TValue>> Associations { get { return this; } }
public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs { get { return this; } }

That means you can really easily be specific:

var query = from x in table.Associations
...;

or

var query = from x in table.KeyValuePairs
...;

Not only does this help keep the compiler happy - it'll help anyone trying to read the code, too. If you find you use one of these much more than the other, you could always make HashTable only implement a single IEumerable<> and type and keep the other property.

Implementing IEnumerator/ IEnumerable with IDispose error

IEnumerator<T> inherits from IDisposable, you so have to implement it too and provide a Dispose method.

IEnumerator<T> inherits from IEnumerator, so you have to implement it too and provide a GetEnumerator() function returning an IEnumerator.

IEnumerator<T> defines a property Current which returns a T, so you have to implement one.


I guess the confusion arises from the fact that the generic IEnumerable<T> and IEnumerator<T> inherit from the non-generic versions (IEnumerable and IEnumerator), demanding to implement methods with the same name but different return value types; and that IEnumerator<T> inherits from IDisposable while IEnumerator does not.


So, in the end, your class should look something like

public class AppAnnieImport : IEnumerator<AppLines>, IEnumerable<AppLines>
{
public int code { get; set; }
public DateTime end_date { get; set; }
public string vertical { get; set; }
public string granularity { get; set; }
public string device { get; set; }
public List<AppLines> AppLine { get; set; }
private int position;

//IEnumerator and IEnumerable require these methods.
public IEnumerator<AppLines> GetEnumerator()
{
return (IEnumerator<AppLines>)this;
}

IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator<AppLines>)this;
}

//IEnumerator
public bool MoveNext()
{
position++;
return (position < AppLine.Count);
}

//IEnumerable
public void Reset()
{ position = 0; }

//IEnumerable
object IEnumerator.Current
{
get { return (AppLine.ToArray())[position] ; }
}

public AppLines Current
{
get { return (AppLine.ToArray())[position] ; }
}

public void Dispose()
{
// do something or not
}
}

making use of explicit interface implementation (you may also want to get rid of the code duplication).

Implementing IEnumerableT in C++/CLI

You must provide an explicit implementation of the non-generic GetEnumerator() method and include the non-generic namespace:

using namespace System::Collections;

....

virtual IEnumerator^ EnumerableGetEnumerator() = IEnumerable::GetEnumerator
{
return GetEnumerator<MyClass^>();
}

Update: As mentioned in the comments, the explicit version of GetEnumerator must be named different to avoid name clash, thus I've named it EnumerableGetEnumerator.

Similarly, in C# you would have to do it like this:

using System.Collections.Generic;

public class MyCollection : IEnumerable<MyClass>
{
public MyCollection()
{
}

public IEnumerator<MyClass> GetEnumerator()
{
return null;
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator<MyClass>();
}
}

Why implement IEnumerable(T) if I can just define ONE GetEnumerator?

Aren't you just moving the boilerplate somewhere else - from writing the IEnumerable.GetEnumeratormethod on each class to calling your AsEnumerable extension every time an IEnumerable<T> is expected? Typically, I would expect an enumerable type to be used for querying far more times than it is written (which is exactly once). This would mean that this pattern will lead to more boilerplate, on average.

Having trouble with an ICollection/IEnumerable operation - won't remove an occurrence

The UnitHistory Class had a logic error in the Equals function. Now that objects could be identified as being equal, the code functions perfectly.



Related Topics



Leave a reply



Submit