Iterators and static class

D

dtarczynski

Hello all.
I have to implement IEnumerator interface in my (static) class. But
compilers throws me an error:
'GetEnumerator': cannot declare instance members in a static class
For example:

private static List<Product> _productsList;
public static List<Product> ProductsList
{
get
{
if (_productsList == null)
_productsList = new List<Product>();
return _productsList;
}
set { _productsList = value; }
}

public IEnumerator GetEnumerator()
{
foreach (Product p in _productsList)
{
yield return p;
}
}


That's why I have question: Can I implement Iterator with static
classes other way?
Thanks in advance
 
J

Jon Skeet [C# MVP]

dtarczynski wrote:

That's why I have question: Can I implement Iterator with static
classes other way?

No. You can't implement any non-empty interface in a static class, as
an interface *insists* on certain instance members being present, and a
static class *prevents* any instance members being present.

Jon
 
D

Dustin Campbell

Not really. The problem is that the foreach statement expects an instance
variable and not a type name. So, this code is illegal:

using System;
using System.Collections;
using System.Collections.Generic;

namespace ConsoleApp
{
static class EnumeratorTest
{
private static List<int> m_IntList = new List<int>(new int[] { 0, 1,
2, 3, 4, 5, 6, 7, 8, 9 });

public static IEnumerator GetEnumerator()
{
foreach (int i in m_IntList)
yield return i;
}
}

class Program
{
static void Main(string[] args)
{
foreach (int i in EnumeratorTest)
Console.WriteLine(i);
}
}
}

This raises the following compiler error: "'ConsoleApp.EnumeratorTest' is
a 'type' but is used like a 'variable'"

However, you *can* add a ForEach method similar to the way it is done by
List<T>.ForEach(). For example:

using System;
using System.Collections;
using System.Collections.Generic;

namespace ConsoleApp
{
static class EnumeratorTest
{
private static List<int> m_IntList = new List<int>(new int[] { 0, 1,
2, 3, 4, 5, 6, 7, 8, 9 });

public static void ForEach(Action<int> action)
{
foreach (int i in m_IntList)
action(i);
}
}

class Program
{
static void Main(string[] args)
{
EnumeratorTest.ForEach(delegate(int i) { Console.WriteLine(i); });
}
}
}


Best Regards,
Dustin Campbell
Developer Express Inc
 
D

Dustin Campbell

No. You can't implement any non-empty interface in a static class, as
an interface *insists* on certain instance members being present, and
a static class *prevents* any instance members being present.

You don't have to implement an interface to create a GetEnumerator() method
that uses an iterator. This code works fine:

using System;
using System.Collections;
using System.Collections.Generic;

namespace ConsoleApp
{
class EnumeratorTest
{
private List<int> m_IntList = new List<int>(new int[] { 0, 1, 2, 3, 4,
5, 6, 7, 8, 9 });

public IEnumerator GetEnumerator()
{
foreach (int i in m_IntList)
yield return i;
}
}

class Program
{
static void Main(string[] args)
{
EnumeratorTest instance = new EnumeratorTest();
foreach (int i in instance)
Console.WriteLine(i);
}
}
}

Best Regards,
Dustin Campbell
Developer Express Inc.
 
M

Martin Z

There's a trick with static functions that return enumerators you can
use.

static class myStaticClass
{
static private object[] myIterable;

public static IEnumerable<object> MyStaticEnumerable() // a method
that returns an enumerable
{
foreach(object obj in myIterable)
{
yield return obj;
}
}
}

this can be used as follows:

foreach (obj in myStaticClass.MyStaticEnumerable())
{
...
}

I'm pretty sure that mess'll work, though I haven't tested it myself.
 
J

Jon Skeet [C# MVP]

Dustin Campbell said:
You don't have to implement an interface to create a GetEnumerator() method
that uses an iterator.

That's true. You do, however, have to have an instance method - which
runs into exactly the same issue.
 
D

Dustin Campbell

That's true. You do, however, have to have an instance method - which
runs into exactly the same issue.

That is the problem. Of course, this begs the question why a static class
is needed in the first place. It seems counterintuitive for a collection
class to be static since you can't make it enumerable and you can't have
static indexers.

Best Regards,
Dustin Campbell
Developer Express Inc.
 
M

Martin Z

Either way, if static-like behaviour is needed, C# has easy idioms for
Singletons. That is, define an instance class, but make the
constructor private - and then give the class itself a static
constructor which in turn constructs the instance object and stores it
in a public static field. Alternately, one can use a property and make
it lazily instantiated, rather than using the static constructor to
construct the single instance object.

Still, I prefer just using a generator to include a method that returns
an IEnumerable if static semantics are desired.
 
D

Dustin Campbell

Either way, if static-like behaviour is needed, C# has easy idioms for
Singletons. That is, define an instance class, but make the
constructor private - and then give the class itself a static
constructor which in turn constructs the instance object and stores it
in a public static field. Alternately, one can use a property and
make it lazily instantiated, rather than using the static constructor
to construct the single instance object.

Still, I prefer just using a generator to include a method that
returns an IEnumerable if static semantics are desired.

Sure, or even the old System.Collections.ICollection interface.

Best Regards,
Dustin Campbell
Developer Express Inc.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top