David Pfeffer
David Pfeffer

Reputation: 39872

Implementing multiple IEnumerables in C#

I have a generic class, Class<T>, that implements IEnumerable<T>. T is also constrained to implement IConvertable.

I also want this class to be able to pretend to be a string-like object, so I want to implement IEnumerable<char>. However, IEnumerable<T> and IEnumerable<char> collide -- what happens if T is char?

Does anyone have any suggestions on how to accomplish this?

EDIT: Here's some clarification -- I'd like to be able to do the following:

public IEnumerator<T> GetEnumerator()
{
    for (var i = _offset; i < _offset + _length; i++)
        yield return _array[i];
}

public IEnumerator<char> GetEnumerator()
{
    for (var i = _offset; i < _offset + _length; i++)
        yield return _array[i].ToChar(null);
}

Upvotes: 3

Views: 337

Answers (3)

LukeH
LukeH

Reputation: 269628

You say that you need your class to "pretend to be a string-like object". Can you make the string-like behaviour more explicit and avoid implementing IEnumerable<char> at all?

public IEnumerator<T> GetEnumerator()
{
    for (var i = _offset; i < _offset + _length; i++)
        yield return _array[i];
}

// either
public IEnumerator<char> GetCharEnumerator()
{
    for (var i = _offset; i < _offset + _length; i++)
        yield return _array[i].ToChar(null);
}

// or
public IEnumerable<char> AsCharSequence()
{
    for (var i = _offset; i < _offset + _length; i++)
        yield return _array[i].ToChar(null);
}

Upvotes: 2

Bonshington
Bonshington

Reputation: 4032

public class myClass<T>() : IEnuerable<T> where T: IConvertable
{
 public override string ToString()
 {
  if(typeof(T).Equals(typeof(char)))
   return this.Select(obj => obj.ToChar(null).ToString()).Aggregate((cur, nex) => cur + "," + nex);;
  else
   return this.Select(obj => obj.ToString()).Aggregate((cur, nex) => cur + "," + nex);
 }
}

or u could just use extension method

public static class extension
{
 public static string To_String<T>(this IEnumerable<T> data) where T:IConvertable
 {
  if(typeof(T).Equals(typeof(char)))
   return data.Select(obj => obj.ToChar(null).ToString()).Aggregate((cur, nex) => cur + "," + nex);;
  else
   return data.Select(obj => obj.ToString()).Aggregate((cur, nex) => cur + "," + nex);
 }
}

or just put if

public IEnumerator<T> GetEnumerator()
{
  if(typeof(T).Equals(typeof(char)))
    for (var i = _offset; i < _offset + _length; i++)
        yield return _array[i].ToChar(null);
  else
    for (var i = _offset; i < _offset + _length; i++)
        yield return _array[i];
}

Upvotes: 1

Eric Lippert
Eric Lippert

Reputation: 660493

Does anyone have any suggestions on how to accomplish this?

Declaration of generic types such that the base types can unify under construction is sometimes illegal and almost always a bad idea. Avoid, avoid, avoid.

My advice: if you want an object that acts like a string then either override ToString(), or declare an explicit (or, I suppose, implicit) conversion to string. If the user wants a sequence of chars then they can obtain one from the string.

Upvotes: 10

Related Questions