Frage

Gibt es eine Möglichkeit in .NET (oder irgendeine Art von Standard-Erweiterungsmethoden) Fragen einer Aufzählung zu fragen?

Zum Beispiel ist das aktuelle Element das erste oder letzte Element in der Aufzählung:

string s = "";

foreach (var person in PeopleListEnumerator) {

  if (PeopleListEnumerator.IsFirstItem) s += "[";

  s += person.ToString();

  if (!PeopleListEnumerator.IsLastItem) s += ",";
  else s += "]";
}
War es hilfreich?

Lösung

Nur um Spaß, eine Lösung für das allgemeine Problem, das nicht begierig Auswertung benötigt und hat einen einzigen lokalen Variable (mit Ausnahme des Enumerator):

static class TaggedEnumerableExtensions
{
    public class TaggedItem<T>
    {
        public TaggedItem(T value, bool isFirst, bool isLast)
        {
            IsFirst = isFirst;
            IsLast = isLast;
            Value = value;
        }
        public T Value { get; private set; }
        public bool IsFirst { get; private set; }
        public bool IsLast { get; private set; }
    }
    public static IEnumerable<TaggedItem<T>> ToTaggedEnumerable<T>(this IEnumerable<T> e)
    {
        using (var enumerator = e.GetEnumerator()) {
            if (!enumerator.MoveNext())
                yield break;
            var current = enumerator.Current;
            if (!enumerator.MoveNext()) {
                yield return new TaggedItem<T>(current, true, true);
                yield break;
            } else {
                yield return new TaggedItem<T>(current, true, false);
            }

            for (;;) {
                current = enumerator.Current;
                if (!enumerator.MoveNext()) {
                    yield return new TaggedItem<T>(current, false, true);
                    yield break;
                }
                yield return new TaggedItem<T>(current, false, false);
            }
        }
    }
}

Test:

class Program
{
    static void Main(string[] args)
    {
        foreach (var item in Enumerable.Range(0, 10).ToTaggedEnumerable()) {
            Console.WriteLine("{0} {1} {2}", item.IsFirst, item.IsLast, item.Value);
        }
    }
}

Andere Tipps

Wenn Sie Ihre Sammlung eine Liste ist, können Sie tun:

string s = "[" + String.Join(",", PeopleList.ToArray()) + "]";

Nicht, dass ich wüsste. Sie können versuchen, solche Erweiterungsmethoden selbst zu schreiben, though. Oder halten Sie den Überblick über die ersten / letzten Punkt an anderer Stelle.

Eric Lippert hatte eine Blog-Post über diese Art von Problem vor kurzem zusammen mit einigen Gedanken darüber, wie die Problembeschreibung zu ändern, genauer zu reflektieren, was Sie eigentlich wollen.

Du bist wahrscheinlich besser dran mit einem String.Join mit einigen LINQ in diesem Fall:

String.Join(
  ",",
  (from p in PeopleListEnumerator
  select p.ToString()).ToArray()
)

Die IEnumerable-Schnittstelle wird nicht definiert, oder die Elemente erwartet, dass es wieder in einer gegebenen Ordnung zu sein. So ist der Begriff der „First“ nicht immer gelten.

Doch für dieses besondere Muster ist das, was ich tue

StringBuilder result = new StringBuilder();
result.Append( '[' );

foreach( var person in PeopleListEnumerator )
{
    if( result.Length > 1 )
        result.Append( ',' );
    result.Append( person.ToString() );
}

result.Append( ']' );

Jon Skeet schrieb Smart-Aufzählungen diese Art von Funktionalität zu bieten und sie sind Teil der MiscUtils Bibliothek.

Das heißt, spezifische Beispiel am besten durch die String.Join () Ansatz gelöst, wie viele andere haben darauf hingewiesen. eine allgemeine string Join(this IEnumerable<T>,string) Erweiterung zu schreiben ist nicht schwer und ist dann verwendbar in allen Situationen mehr ohne lästige temporäre Arrays zu müssen.

Mit LINQ können Sie tun:

string s = 
    string.Format("[{0}]", string.Join(",",PeopleListEnumerator.Select(p => p.ToString()).ToArray()));

Ich finde ich definiert und einen „Bool ersten“ lokalen Variable verwenden, zum Beispiel:

string s = "[";
bool first = true;

foreach (var person in PeopleListEnumerator) {

  if (first)
    first = false;
  else
    s += ",";
  s += person.ToString();
}
s += "]";

Dieser Code genau übereinstimmt, was Sie wirklich erreichen wollen:

StringBuilder s = new StringBuilder("[");
string delimiter = "";

foreach (var person in PeopleListEnumerator) {  
  s.Append(delimiter).Append(person.ToString());
  delimiter = ",";
}

return s.Append("]").ToString();

So wie ich diese Katze Haut würde (ja, es gibt viele Möglichkeiten, dass) wäre:

StringBuilder sb = new StringBuilder();

foreach (var person in PeopleListEnumerator )
{
    sb.AppendFormat(",{0}", person.ToString());
}

string s = "[" + sb.ToString().Substring(1) + "]";

Hope, das hilft ...

In .NET Aufzählungen haben kein Konzept der Ordnung, mit Ausnahme von Wert. Wenn Sie eine erste und letzte Aufzählung wollen würde ich vorschlagen, explizit zu definieren, was diese ersten und letzten Werte sind. Die folgende Aufzählung ist ein Beispiel dafür:

public enum PlayerType : byte
{
    Starter = byte.MinValue,
    RegularPlayer = 1,
    BenchWarmer = 2,
    Closer = byte.MaxValue
}

Sie können dann ausdrücken etwas Ähnliches wie die folgenden:

List<byte> values = new List<byte>((byte[])Enum.GetValues(typeof(PlayerType)));

PlayerType starter = (PlayerType)values.Min();
PlayerType closer = (PlayerType)values.Max();
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top